背包九讲之二(完全背包)

 1 /*
 2 有n种物品和一个容量为v的背包,每件物品可以无限使用,
 3 第i件物品的费用为c[i],价值为w[i],求解哪些物品装入背包
 4 费用不超过背包容量且价值总和最大
 5 基本思路是dp[i][j] = max{dp[i-1][j-k*c[i]] k*c[i]<=j}
 6 和01背包一样有V*N个状态,但是每个状态的求解不再是O(1)了,
 7 求解状态dp[i][j]是O(j/c[i]),总的时间复杂度超过O(V*N)
 8 
 9 可以转化为01背包问题从而求解
10 (1)第i件物品可以转化为v/c[i]件物品,从而转化为01背包问题
11 (2)一种更加好的方法是将第二种物品转化为费用c[i]*2^k,价值w[i]*2^k
12     的若干件物品,其中k满足c[i]*2^k<=v.这是二进制的思想。因为不管最优策选择
13     几件第i中物品,都可以用若干个2^k件物品来表示,这样就把每种物品拆分为
14     log(v/c[i])种物品
15 
16 但是有更优的O(VN)算法
17     for(i=1; i<=n; ++i)
18     for(j=v[i]; j<=v; ++j)
19         dp[j] = max(dp[j],dp[j-c[i]+w[i]);
20 
21 其实可以这么想  dp[i][j] = max(dp[i-1][j],dp[i][j-v[i]]+w[i]);
22 dp[i][j]可以转化为上一层的dp[i-1][j],也可以转化为这一层左边的状态
23 所以要求比j小的状态要算出来,所以要求j从0-->v
24 就是
25 for(i=1; i<=n; ++i)
26     for(j=0; j<=v; ++j)
27     {
28         dp[i][j] = dp[i-1][j];
29         if(j>=v[i])
30             dp[i][j] = max(dp[i][j],dp[i][j-c[i]]+w[i]);
31     }
32 转化为一维的状态就是
33 for(i=1; i<=n; ++i)
34 for(j=v[i]; j<=v; ++j)
35     dp[j] = max(dp[j],dp[j-c[i]]+w[i]);
36 */
37 #include <stdio.h>
38 #include <string.h>
39 int dp[111][1111];
40 int dp2[1111];
41 int c[111],w[111];
42 inline int max(const int &a, const int &b)
43 {
44     return a < b ? b : a;
45 }
46 int main()
47 {
48     int n,v,i,j,k;
49     while(scanf("%d%d",&n,&v)!=EOF)
50     {
51         for(i=1; i<=n; ++i)
52             scanf("%d",&w[i]);
53         for(i=1; i<=n; ++i)
54             scanf("%d",&c[i]);
55         memset(dp,0,sizeof(dp));
56         memset(dp2,0,sizeof(dp2));
57         for(i=1; i<=n; ++i)
58         {
59             for(j=0; j<=v; ++j)
60             {
61                 dp[i][j] = dp[i-1][j];
62                 if(j>=c[i])
63                 {
64                     dp[i][j] = max(dp[i][j],dp[i][j-c[i]]+w[i]);
65                     dp2[j] = max(dp2[j],dp2[j-c[i]]+w[i]);
66                 }
67             }                
68         }
69         
70         printf("%d
",dp[n][v]);
71         printf("%d
",dp2[v]);
72     }
73     return 0;
74 }
75 
76 /*
77 sample input:
78 5 10
79 1 2 5 4 6
80 2 2 6 5 4
81 
82 sample output:
83 
84 */
原文地址:https://www.cnblogs.com/justPassBy/p/4278759.html