1 /*
2 有n个物品和一个容量为V的背包,第i件物品的费用是c[i],价值是w[i]
3 求解哪些物品装入背包使价值总和最大
4 dp[i][j] dp[i][j] 为前i件物品放进容量为j的背包的最大价值
5 dp[i][j] = max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);
6 */
7 #include <stdio.h>
8 #include <string.h>
9 int dp[111][1111];
10 int dp2[1001];
11 int c[111],w[111];
12 bool flag[111];
13 inline int max(const int &a, const int &b)
14 {
15 return a < b ? b : a;
16 }
17 int main()
18 {
19 int n,v,i,j;
20 while(scanf("%d%d",&n,&v)!=EOF)
21 {
22 memset(dp,0,sizeof(dp));
23 dp2[0] = 0;
24 for(i=1; i<=n; ++i)
25 dp2[i] = 1<<30;
26 memset(flag,false,sizeof(flag));
27 for(i=1; i<=n; ++i)
28 scanf("%d",&w[i]);
29 for(i=1; i<=n; ++i)
30 scanf("%d",&c[i]);
31 for(i=1; i<=n; ++i)//时间空间复杂度均为O(VN)
32 for(j=0; j<=v; ++j)
33 {
34 dp[i][j] = dp[i-1][j];
35 if(j>=c[i])
36 dp[i][j] = max(dp[i][j],dp[i-1][j-c[i]]+w[i]);
37 }
38 for(i=1; i<=n; ++i)
39 for(j=v; j>=0; --j)
40 {
41 if(j>=c[i])
42 dp2[j] = max(dp2[j],dp2[j-c[i]]+w[i]);
43 }
44 printf("%d\n",dp[n][v]);
45 printf("%d\n",dp2[v]);
46 /*时间复杂度不能优化了,但是空间可以优化到O(V)
47 for(i=1; i<=n; ++i)
48 for(j=v; j>=0; --j)//将循环改为这样也是成立的
49 那么每一个dp[i][j] 都是继承自上一层的dp[i-1][j] 或者dp[i-1][j-c[i]]
50 那么j是大于等于j或者j-c[i]的。
51 那么就可以这样
52 for(i=1; i<=n; ++i)
53 for(j=v; j>=c[i]; --j)//必须是从后忘前
54 {
55 dp2[j] = max(dp2[j],dp[j-c[i]+w[i]]);//这一层继承继承自上一层,这种数组叫做滚动数组
56 }
57 */
58 //下面是判断哪几个背包被选
59 int Max = dp[n][v];
60 for(i=n; i>=1; --i)
61 {
62 if(dp[i-1][v]>= Max)
63 flag[i] = false;
64 else
65 {
66 flag[i] = true;
67 v -= c[i];
68 Max -= w[i];
69 }
70 }
71 if(flag[1])
72 printf("1");
73 else
74 printf("0");
75 for(i=2; i<=n; ++i)
76 if(flag[i])
77 printf(" 1");
78 else
79 printf(" 0");
80 printf("\n");
81 }
82 return 0;
83 }
84 /*
85 5 10
86 6 3 5 4 6
87 2 2 6 5 4
88 Sample Output:
89 15
90 1 1 0 0 1
91 */
92 /*
93 另外还有就是求背包的最优解过程中,有两种要求:
94 (1)要求背包装满,且价值最大(所以可能导致无解的情况发生)
95 (2)只要求价值最大
96 这两种问法差别在于初始化
97 (1)将dp[0][0]初始化为0,其他的初始化为-INF,这是由题目的性质导致的
98 初始的时候什么都不装,但是背包有容量而没装满是不合法的,所以定义-INF为不合法的
99 如果要求背包装满,那么dp[i][j]表示的含义就变为了前i个物品装满容量为j的背包的最大价值
100 dp[i][j] = max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);
101 如果dp[i-1][j],dp[i-1][j-c[i]]+w[i] ,这两个状态是不合法的,那么dp[i][j]也是不合法的
102 (2)都初始化为0
103
104 */