二维费用背包,有一个小问题


#include<iostream>
using namespace std;
int v[1005],m[1005],w[1005];
int dp[1005][1005];
int main()
{
    int N,V,M;
    cin>>N>>V>>M;
    for(int i=1;i<=N;i++)cin>>v[i]>>m[i]>>w[i];
    
    for(int k=1;k<=N;k++)
    {
        for(int i=V;i>=0;i--)
        {
            for(int j=M;j>=0;j--)
            {
                //dp[i][j]=dp[i-1][j];
                if(i>=v[k]&&j>=m[k])dp[i][j]=max(dp[i][j],dp[i-v[k]][j-m[k]]+w[k]);
            }
        }
    }
    cout<<dp[V][M]<<"\n";
    return 0;
}

```c++
#include<iostream>
using namespace std;
int v[1005],m[1005],w[1005];
int dp[1005][1005];
int main()
{
    int N,V,M;
    cin>>N>>V>>M;
    for(int i=1;i<=N;i++)cin>>v[i]>>m[i]>>w[i];
    
    for(int k=1;k<=N;k++)
    {
        for(int i=V;i>=0;i--)
        {
            for(int j=M;j>=0;j--)
            {
                //dp[i][j]=dp[i-1][j];
                if(i>=v[k]&&j>=m[k])dp[i][j]=max(dp[i][j],dp[i-v[k]][j-m[k]]+w[k]);
            }
        }
    }
    cout<<dp[V][M]<<"\n";
    return 0;
}


注释掉的部分不懂,为什么要注释掉

因为你的程序已经将01背包一维优化过,所以不需要进行你注释的那一部分的状态转移过程,而二维费用背包就是在01背包的基础上添加了一个限制,只需枚举当前容量(V)时,枚举所有的(M)。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/7568226
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:二叉树的层次遍历和分层遍历,每层个数,打印每层最左端节点
  • 除此之外, 这篇博客: 二进制,八进制,十进制,十六进制的相互转换【简单易懂】中的  练一练手: 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    P1143 进制转换

    #include<bits/stdc++.h>
    using namespace std;
    string s;
    int a,b;
    int wei,sum,num;
    int c[10000010];
    int main()
    {
    	cin>>a>>s>>b;
    	for(int i=0;i<s.size();i++)
    	{
    		if(s[i]<'A')
    		{
    			wei=pow(a,s.size()-1-i);    //从大向小取位
    			wei*=(s[i]-'0');
    			sum+=wei;
    		}
    		else
    		{
    			wei=pow(a,s.size()-1-i);
    			wei*=(s[i]-'A'+10);
    			sum+=wei;
    		}
    	}
                                           //sum为a进制转化为十进制的值
    	while(sum>0)
    	{
    		c[num++]=sum%b;    //连除法
    		sum/=b;
    	}
    	for(int i=num-1;i>=0;i--)    //对应前面,“从下到上输出”
    	{
    		if(c[i]>=10) printf("%c",c[i]+'A'-10);    //可能是字符,cout默认数字
    		else cout<<c[i];
    	}
    	 
    	return 0;
    }
    

  • 您还可以看一下 刘磊老师的计算机进制转换课程中的 十进制不规则小数转换为二进制小节, 巩固相关知识点
  • 以下回答来自chatgpt:

    根据提供的参考资料,可以看出这部分的代码是关于一个数据表的输入和输出问题的解决方案。代码中的注释的目的是为了提醒用户选择对应的行或列进行求和,并通过函数指针调用相应的求和函数。

    这部分代码的注释对解决问题并没有实质性的影响,注释的目的是为了给用户提供清晰的提示和说明。因此,可以认为注释掉这部分代码并不会影响问题的解决。

    如果想要具体了解为什么注释掉这部分代码,可以与编写代码的人员进行交流,他们可能有具体的原因和解释。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

以下内容引用自GPT,有用希望点个采纳:
当其中一句代码 dp[i][j]=dp[i-1][j]; 被注释掉时,意味着在计算状态 dp[i][j] 时不考虑物品 k

在这段代码中,通过三重循环遍历每个状态 (i, j) ,其中 i 表示可用的体积,j 表示可用的重量。

原本的那行被注释掉的代码 dp[i][j]=dp[i-1][j]; 的作用是将当前状态 (i, j) 的最优值初始化为上一个状态 (i-1, j) 的最优值。这个初始化操作是为了处理不选取物品 k 的情况,将状态 dp[i][j] 的值设置为上一行相同列的值。

然而,当这行代码被注释掉时,当前状态 (i, j) 的值不再初始化为上一个状态 (i-1, j) 的值,而是经过下述判断赋值操作:

if(i>=v[k]&&j>=m[k])dp[i][j]=max(dp[i][j],dp[i-v[k]][j-m[k]]+w[k]);

这行代码判断当前体积 i 和重量 j 是否足够容纳物品 k,如果足够,则尝试将物品 k 放入背包中并根据价值 w[k] 更新状态 dp[i][j] 的值。

所以,如果注释掉 dp[i][j]=dp[i-1][j]; 这行代码,意味着不考虑不选取物品 k 的情况,而只考虑选取物品 k 的情况来更新状态 dp[i][j] 的值。这样的处理方式通常用于解决背包问题中的物品不可重复选取的情况。