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 0x3f3f3f3f using 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 0x3f3f3f3f using 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; }