状态转移方程为:dp[i][j] 表示i件物品放入容量为j的背包中的最大价值
dp[i][j] = max(dp[i-1][j], dp[i-1][j-size[i]]+value[i]);
分析:第i件物品放不放入背包有两种选择:若不放进背包,则dp[i][j]的值等于i-1件物品放进容量为j的背包中的最大价值,即
dp[i][j] = dp[i-1][j],
若放进背包的话, 则dp[i][j]的值等于i-1件物品放进容量为j-size[i]的背包中的最大价值,即dp[i][j] = dp[i-1][j-size[i]]+value[i] ;
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 1010; typedef struct Apple { int size,value; }Apple; Apple apple[maxn]; int res[maxn][maxn]; int main() { int n,v; while(scanf("%d%d",&n,&v)==2 && (n&&v)) { memset(res,0,sizeof(res)); int sum = 0; for(int i=1;i<=n;++i) { scanf("%d%d",&apple[i].size,&apple[i].value); } for(int i=1;i<=n;++i) for(int j=1;j<=v;++j) if(apple[i].size<=j)//当背包的空间大于 第i个苹果的大小时 res[i][j] = max(res[i-1][j],res[i-1][j-apple[i].size]+apple[i].value); else res[i][j] = res[i-1][j];//否则,背包空间装不下此苹果,此时的装入苹果的价值 等于 不放入这个苹果的背包内苹果的价值 printf("%d\n",res[n][v]); } return 0; }
上面计算res[i][j]可以看出,在计算res[i][j]时只使用了res[i-1][0……j],
没有使用其他子问题,因此在存储子问题的解时,只存储res[i-1]子问题的解即可。
这样可以将res降成一维数组!!!
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 1010; typedef struct Apple { int size,value; }Apple; Apple apple[maxn]; int res[maxn]; int main() { int n,v; while(scanf("%d%d",&n,&v)==2 && (n&&v)) { memset(res,0,sizeof(res)); int sum = 0; for(int i=1;i<=n;++i) scanf("%d%d",&apple[i].size,&apple[i].value); for(int i=1;i<=n;++i) for(int j=v;j>=apple[i].size;--j) res[j] = max(res[j],res[j-apple[i].size]+apple[i].value); printf("%d\n",res[v]); } return 0; }