背包九讲第一讲-简单的0/1背包问题有感1.3

来源:互联网 发布:红米手机怎么清除数据 编辑:程序博客网 时间:2024/06/05 03:51

如何改进呢?

我觉得大家还是可以先看看这一幅图


ok。。。。。。我们先focus on输出14,那部分正确的。
0 0 5 5 5 5 5
0 0 5 8 8 13 13
0 0 5 8 9 13 14
不知道大家对于这个有没有什么想法。。。。。。
是不是觉得,好像有一些东西是重复的,没用的。
我那时候看上去我觉得,可能能够通过使用dp一维数组来降低我们的复杂度。
事实上看资料发现,的确如此,但是我犯了一个错误。

思路

我们可以直接用一个dp[j]数组,注意!这里的dp[j]数组就是说,当现在空间限制为j时候的最大价值和!
状态转移方程:
if(j-w[i]>=0)bag[j]=max(bag[j],bag[j-w[i]]+v[i]);
初值:
一开始我把dp数组从j=0~zone都赋值了0;因为现在没有一件物品,对应了每个空间限制的最大价值和都是0!
然后我们从第一件物品开始,一件一件的考虑

这个时候我稍稍将代码改动,即可得出:

#include<iostream>#include<cmath>#include<algorithm>using namespace std;long long bag[10001];int main(){int n=0;int zone=0;int v[101];int w[101];while(cin>>n){cin>>zone;for(int i=1;i<=n;i++){cin>>w[i]>>v[i];}for(int i=0;i<=zone;i++)bag[i]=0;for(int i=1;i<=n;i++){for(int j=0;j<=zone;j++){if(j-w[i]>=0)bag[j]=max(bag[j],bag[j-w[i]]+v[i]);}for(int i=0;i<=zone;i++)cout<<bag[i]<<" ";cout<<endl;}}}

但是因为我的考虑不周,出现了错误。

大家发现了吗,bug在于,同一件物品在足够大的背包空间限制下,可以自己不断叠加!!
我曾经尝试进行下面的补救:
如果能够进行第一次优化,那后面的就直接赋值,不再进行状态转移。
但是这引起了另外一个问题。。。。。。无法照顾到背包容量足够大到可以容纳几件物品。
所以。。。。我找资料寻求帮助。。。。。
大家也可以想一想,整体思路是没有错的,但是我们应该如何修改呢?








没错!j从zone开始递减!就可以避免了自己的在足够大背包空间的限制下进行叠加!!!

怎么样?是不是很巧妙!!对应的dp[zone]就是我们在所要求的背包容积下的最大价值和!!

代码展示

#include<iostream>#include<cmath>#include<algorithm>using namespace std;long long bag[10001];int main(){int n=0;int zone=0;int v[101];int w[101];while(cin>>n){cin>>zone;for(int i=1;i<=n;i++){cin>>w[i]>>v[i];}for(int i=0;i<=zone;i++)bag[i]=0;for(int i=1;i<=n;i++){for(int j=zone;j>=0;j--){if(j-w[i]>=0)bag[j]=max(bag[j],bag[j-w[i]]+v[i]);}for(int i=0;i<=zone;i++)cout<<bag[i]<<" ";cout<<endl;}}}

---还有什么要注意的呢???
未完待续。。。。。。