题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2602
这是做的第一道01背包的题目。题目的大意是有n个物品,体积为v的背包。不断的放入物品,当然物品有各自的体积和价值。在不超过总体积v的情况下,问能够达到的最大价值。并且物品是一个一个放入的。最后若有剩余的体积也不会填满。
刚开始是用贪心做的。将价值与体积的比值设定为一个值,即单位价值。然后按照单位价值排序,挨个取物品,考虑到了体积为0的情况,就将单位价值设定为无穷大。但是这样做并不能保证最优解。例如:总体积为5,一共有两个物品。第一个体积4,价值6。第二个体积为2,价值为4。很明显第一个更合适,但是按照单位价值比来做。结果就不是这样的了。所以贪心法不适合这样的01背包。但是适合物品可以只取一部分的01背包,是的最后的背包肯定会被刚好填满。
在这道题中用数组dp来保存运算结果。例如dp[i][j]表示前i个物品放入体积为j的背包中。
判断第i个物品能否放入大小为j的背包中。如果可以,是放?还是不放?
重点是可以放的情况!
最后需要注意的是体积可以为0,同时最后结果保存在dp[n][v]中。
附上源代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string> 5 #include<string.h> 6 #include<math.h> 7 #include<map> 8 #include<vector> 9 #include<algorithm> 10 using namespace std; 11 #define MAX 0x3f3f3f3f 12 #define MIN -0x3f3f3f3f 13 #define N 1005 14 int val[N]; 15 int vol[N]; 16 int dp[N][N]; 17 int main() 18 { 19 int T; 20 int i, j; 21 int n, v;//物品,背包体积 22 scanf("%d", &T); 23 while (T--) 24 { 25 scanf("%d%d", &n, &v); 26 for (i = 1; i <= n; i++) 27 scanf("%d", &val[i]); 28 for (i = 1; i <= n; i++) 29 scanf("%d", &vol[i]); 30 memset(dp, 0, sizeof(dp)); 31 for (i = 1; i <= n; i++) 32 { 33 for (j = 0; j <= v; j++)//体积可以是0 34 { 35 if (vol[i] <= j)//第i个物品的体积可以放到大小为j的背包中 36 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - vol[i]] + val[i]);//如果不放,前i-1件物品放入大小为v的包中。放的话,前i-1件物品放入v-vol[i]大的背包中 37 else 38 dp[i][j] = dp[i - 1][j];//放不进去的话,相当于前i-1件物品放入大小为v的背包中 39 } 40 } 41 printf("%d ", dp[n][v]); 42 } 43 return 0; 44 }
顺便在附上错误的贪心代码,警告自己!
1 #include<iostream> 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string> 5 #include<string.h> 6 #include<math.h> 7 #include<map> 8 #include<vector> 9 #include<algorithm> 10 using namespace std; 11 #define MAX 0x3f3f3f3f 12 #define MIN -0x3f3f3f3f 13 struct node 14 { 15 int volume; 16 int vaule; 17 double f; 18 }ans[1005]; 19 int cmp(const void *a, const void *b) 20 { 21 struct node *aa = (node *)a; 22 struct node *bb = (node *)b; 23 return(((aa->f)<(bb->f)) ? 1 : -1); 24 } 25 int main() 26 { 27 int T; 28 int N, V; 29 int i; 30 int val;//价值 31 int vol;//体积 32 scanf("%d", &T); 33 while (T--) 34 { 35 scanf("%d%d", &N, &V); 36 for (i = 0; i < N; i++) 37 { 38 scanf("%d", &ans[i].vaule); 39 } 40 for (i = 0; i < N; i++) 41 { 42 scanf("%d", &ans[i].volume); 43 if (ans[i].volume == 0) 44 ans[i].f = MAX; 45 else 46 ans[i].f = ans[i].vaule*1.0 / ans[i].volume; 47 } 48 qsort(ans, N, sizeof(ans[0]), cmp); 49 val = 0; 50 vol = 0; 51 ans[N].vaule = 0; 52 ans[N].volume = 0; 53 ans[N].f = 0; 54 for (i = 0; i <= N; i++) 55 { 56 if (vol <= V) 57 { 58 val = val + ans[i].vaule; 59 vol = vol + ans[i].volume; 60 } 61 else if (vol>V) 62 { 63 val = val - ans[i - 1].vaule; 64 //vol = vol - ans[i - 1].volume; 65 //val = val + (V - vol)*(int)ans[i - 1].f; 66 break; 67 } 68 } 69 printf("%d ", val); 70 } 71 return 0; 72 }