假设有两个物品 第一个物品 w=2 v=1 第二个物品 w=2 v=2
在将背包由二维转化为一维进行优化的时候
如果正常逆序进行dp
dp[1][4]=1; dp[1][2]=1; dp[2][4]=max(dp[1][4],dp[1][4-2]+2)=3; dp[2][2]=2;
这是正确做法
但是如果正序进行dp
do[1][4]=1; dp[1][2]=1; dp[2][2]=2; dp[2][4]=max(dp[1][4],dp[2][4-2]+2)=4;
注意上面为dp[1][4-2]而下面为dp[2][4-2] 原因是dp[2][2]已更新
出错的原因就是 第二个物品取了两次 其实这也就是完全背包的来源
就是dp[i][j]由dp[i][j-w[i]]+v[i]推过来的 而不是dp[i-1][j-w[i]]+v[i]
会导致结果偏大
最初的想法为顺序会更对 结果更大更准确
经代码验证想法错误 但是发现了完全背包
下一步多重背包
以下为验证代码:
#include <iostream>
#include <string.h>
using namespace std;
int dp[1005];
int main()
{
int i,j,n,m,t;
int v[1005]={0};
int w[1005]={0};
cin>>t;
while(t--)
{
cin>>n>>m;
memset(dp,0,sizeof(dp));
memset(v,0,sizeof(v));
memset(w,0,sizeof(w));
for(i=1;i<=n;i++)
cin>>v[i];
for(i=1;i<=n;i++)
cin>>w[i];
//正确的逆向跑
for(i=1;i<=n;i++)
{for(j=m;j>=w[i];j--)
{
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
cout<<dp[j]<<" ";
}cout<<endl;
}
cout<<endl<<endl;
//错误的正向跑
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{for(j=w[i];j<=m;j++)
{
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
cout<<dp[j]<<" ";
}cout<<endl;
}
cout<<endl;
//cout<<dp[m]<<endl;
}
return 0;
}