题目
解释
- 解法一(二维解法)
- f[i][j],第一维度i表示只看前i个物品,第二维度表示总体积是j,存放的数值代表当前总价值最大
- 在进行第i个物品选择判断时,将当前不选择物品的总价值与选择物品后的总价值(注意到第二维的变化)进行了比较
- 最后输出看完第i个物品后,总价值最大的情况
- 解法二(一维解法)
- 将第一维压缩,但是思路与二维的情形相同
- 最终只需要输入总体积为最大时的f[m]即可,因为此时已经考虑完了全部物品的情形
关于二维和一维的不同之处
在于j的遍历顺序
代码段
解法一(二维解法)
#include<iostream>
const int N=1010;
int n,m;
int w[N],v[N];
int dp[N][N];
using namespace std;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>v[i]>>w[i];
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
//这里j也可以从1开始,
//因为当空间大小为0时dp[i][0]必然是0,因为无法选择任何物品
{
dp[i][j]=dp[i-1][j];//如果不选择当前物品
if(j-v[i]>=0)
//如果选择且当前背包容量足够的话
//选择当前物品相当于在没选择时的总空间大小j-v[i]情况下加上了w[i]
dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+w[i]);
}
cout<<dp[n][m]<<endl;
}
解法二(一维解法)
#include<iostream>
using namespace std;
const int N=1010;
int f[N],v[N],w[N];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
for(int i=1;i<=n;i++)
for(int j=m;j>=v[i];j--)
//如果j正序,则可能下标较小的先更新,那么这时就不是上一轮的f[j]了
{
f[j]=max(f[j],f[j-v[i]]+w[i]);
}
cout<<f[m]<<endl;
return 0;
}