注意至少取一个,仔细分析一下,此时光靠一个一维数组是不可以完成状态转移的,必须用二维数组或两个一维数组(滚动数组)。
建议多用二维数组,二维数组比较好理解,不容易出错,除非数据量太大,二维开不下。当然,如果对状态转移理解的比较深刻可以尝试着写成滚动数组。
先讲一讲二维数组的做法:
dp[i][j]表示进行到了第i组容量为j所装载的最大价值。
则dp[i][j]这个状态必须从dp[i-1][j-w[x]]+p[x] (选了第1个第i组的物品),dp[i][j-w[x]]+p[x](已经选过第i组的物品,这次又选了第i组的物品),dp[i][j](不选这个物品);
所以状态转移方程为:
dp[i][j]=max(dp[i][j],max(dp[i][j-w[x]]+p[x],dp[i-1][j-w[x]]+p[x]));
二维数组版:
View Code
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define INF 1<<29 int n, m, k; int w[101],p[101],z[101]; int dp[12][10003]; int main() { int i, j, x; while(~scanf("%d%d%d",&n,&m,&k)) { for(i=1;i<=n;i++) scanf("%d%d%d",&z[i],&w[i],&p[i]); for(j=0;j<=m;j++)dp[0][j]=0;//最开始层赋0 for(i=1;i<=k;i++) //其它层赋值-INF for(j=0;j<=m dp[i][j]=-INF; for(i=1;i<=k;i++) for(x=1;x<=n;x++) for(j=m;j>=0;j--) if(z[x]==i) if(j>=w[x]) dp[i][j]=max(dp[i][j],max(dp[i][j-w[x]]+p[x],dp[i-1][j-w[x]]+p[x])); // 如果要写成把2个比较拆开来写的 请注意: //下面两个顺序不能换,如果换了,当出现w[x]==0时,会加2次。 //dp[i][j]=max(dp[i][j],dp[i][j-w[x]]+p[x]); //dp[i][j]=max(dp[i][j],dp[i-1][j-w[x]]+p[x]); if(dp[k][m]<0)printf("Impossible\n"); else printf("%d\n",dp[k][m]); } return 0; }
滚动数组版1
View Code
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define INF 1<<29 int n, m, k; int w[101],p[101],z[101]; int dp[10003],tmp[10003]; int main() { int i, j, x; while(~scanf("%d%d%d",&n,&m,&k)) { for(i=1;i<=n;i++) scanf("%d%d%d",&z[i],&w[i],&p[i]); memset(dp,0,sizeof(dp)); for(i=1;i<=k;i++) { for(j=m;j>=0;j--) //每次状态转移前 { tmp[j]=dp[j]; //将讲前一轮的状态转移到tmp[] dp[j]=-INF; //当前的状态dp[]初始化 } for(x=1;x<=n;x++) for(j=m;j>=0;j--) if(z[x]==i) if(j>=w[x]) dp[j]=max(dp[j],max(dp[j-w[x]]+p[x],tmp[j-w[x]]+p[x])); } if(dp[m]<0)printf("Impossible\n"); else printf("%d\n",dp[m]); } return 0; }
滚动数组版2:
View Code
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define inf 1<<29 int n, sum, m; int dp[10003]; int z[101], w[101], p[101]; int main() { int i, j, k; while( ~scanf("%d%d%d", &n, &sum, &m) ) { for(i = 1; i <= n; i++) scanf("%d%d%d", &z[i], &w[i], &p[i]); int g1 = 0, g2 = 1; for(i = 0; i <= sum; i++) dp[g1][i] = 0; for(k = 1; k <= m; k++) { for(j = 0; j <= sum; j++) dp[g2][i] = -inf; for(j = sum; j >= 0; j--) for(i = 1; i <= n; i++) if(z[i] == k) { if(w[i] <= j) dp[g2][j] = max( dp[g2][j], max ( dp[g2][j - w[i]] + p[i], dp[g1][j - w[i]] + p[i] ) ); } g1 = !g1; g2 = !g2; } printf("%d\n", dp[g1][sum]); } return 0; }