HDU 2602 Bone Collector(01二维背包&一维背包&滚动数组优化二维背包的原理 )

来源:互联网 发布:数控编程代码大全 编辑:程序博客网 时间:2024/06/15 12:41

01背包模板,注意一点当枚举背包容量的时候控制当满足j>=w[i]才进行比较否则直接进行从上一阶段推下来。


#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<string>#include<queue>#include<map>#include<stack>#define L1 long long#define L2 int#define inf 0x3f3f3f3fusing namespace std;const int m1=1001000;const int m2=1010;L2 v[10001],w[10001];L2 dp[1006][1006];int main(){    int n,m,i,j,k,cla,p;    scanf("%d",&cla);    while(cla--){        scanf("%d%d",&n,&p);        for(i=1;i<=n;i++){            scanf("%d",&v[i]);        }        for(j=1;j<=n;j++){            scanf("%d",&w[j]);        }        memset(dp,0,sizeof(dp));        for(i=1;i<=n;i++){            for(j=p;j>=0;--j){                if(j>=w[i])                dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);                else                dp[i][j]=dp[i-1][j];            }        }        printf("%d\n",dp[n][p]);    }    return 0;}



一维数组优化:

 上边的二维数组主要是通过dp[i][j]将所有状态都保存了下来。但是我们每次都仅仅要当前和之前i-1的状态即可。

所以可以转化为dp[j]=max(dp[j],dp[j-w[i]]+v[i])的状态。等号左边的dp[j]表示dp[i][j]而右边的是dp[i-1][j],含义不同。

那么再说说顺序逆序枚举背包大小的原因:

顺序枚举,它会重复的装入某个物品,而且尽可能多的,使价值最大,当然不会不超过背包容量。那么dp[j-w[i]+v[i]]代表的含义就完全变了。

变成了dp[i][j-w[i]+v[i]],即是第i次而不是i-1次的问题。但是逆序则不会。


#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<string>#include<queue>#include<map>#include<stack>#define L1 long long#define L2 int#define inf 0x3f3f3f3fusing namespace std;const int m1=1001000;const int m2=1010;L2 v[10001],w[10001];L2 dp[1006];int main(){    int n,m,i,j,k,cla,p;    scanf("%d",&cla);    while(cla--){        scanf("%d%d",&n,&p);        for(i=1;i<=n;i++){            scanf("%d",&v[i]);        }        for(j=1;j<=n;j++){            scanf("%d",&w[j]);        }        memset(dp,0,sizeof(dp));        for(i=1;i<=n;i++){            for(j=p;j>=w[i];j--){                    dp[j]=max(dp[j],dp[j-w[i]]+v[i]);            }        }        printf("%d\n",dp[p]);    }    return 0;}


0 0
原创粉丝点击