来源:刘汝佳《算法竞赛入门经典--训练指南》 P60 问题4:
问题描述:有n种物品,每种只有一个,第i种物品的体积为Vi,重量为Wi。选一些物品装到一个容量为C的背包中,使得背包内物品在总体积不超过C的前提下重量尽量大。其中,1<=n<=100。1<=V<=C<=10000。1<=Wi<=10^6。
分析:用f[i][j]表示“把前i个物品装到容量为j的背包中的最大总重量”,则状态转移方程为f[i][j] = Max{f[i-1][j],f[i-1][j-Vi]+Wi | Vi<=j};
滚动数组优化后代码:
1 memset(f,0,sizeof(f)); 2 for(int i=1; i<=n; i++) 3 { 4 scanf("%d %d",&V,&W); 5 for(int j=C; j>=0; j--) 6 { 7 if(j>=V) 8 f[j] = Max(f[j],f[j-V]+W); 9 } 10 }
例题来源:http://acm.hdu.edu.cn/showproblem.php?pid=2602
例题:hdu 2602
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
题意:给一个体积为V( V <= 1000)的背包和n(n <= 1000 )个骨头,每个骨头i有各自的体积volume[i]和价格value[i],求在不超过背包体积V的前提下往背包里装骨头的最大价值。
代码实现:
1 #include "stdio.h" 2 #include "string.h" 3 #define N 1005 4 int dp[N]; 5 int value[N]; //价值数组 6 int volume[N]; //体积数组 7 8 int Max(int a,int b) { return a>b?a:b; } 9 10 int main() 11 { 12 int T; 13 int n,V; //n为骨头数量,V为背包体积 14 int i,j,v,w; 15 scanf("%d",&T); 16 while(T--) 17 { 18 scanf("%d %d",&n,&V); 19 memset(dp,0,sizeof(dp)); 20 for(i=0; i<n; i++) 21 scanf("%d",&value[i]); 22 for(i=0; i<n; i++) 23 scanf("%d",&volume[i]); 24 for(i=0; i<n; i++) 25 { 26 v = volume[i]; //第i个骨头的体积 27 w = value[i]; //第i个骨头的价值 28 for(j=V; j>=v; j--) 29 dp[j] = Max(dp[j],dp[j-v]+w); 30 } 31 printf("%d\n",dp[V]); 32 } 33 return 0; 34 }