hdu 2191 多重背包

  题目链接:hdu 2191

  题意很明显,数据规模也比较小,不过这题的数据还是很强的,多重背包我之前一直没有了解透切,所以也 wa 了不知多少次了,先来个朴素的比较暴力的版本:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define  sd(x)  scanf("%d",&(x))
 6 #define  sd2(x,y)  scanf("%d %d",&(x),&(y))
 7 #define  sd3(x,y,z)  scanf("%d %d %d",&(x),&(y),&(z))
 8 
 9 int dp[103][103];
10 
11 int main() {
12     int t,n,m,p,h,c;
13     sd(t);
14     while(t--) {
15         sd2(n,m);
16         memset(dp, 0, sizeof(dp));
17         for(int i = 1; i <= m; ++i) {
18             sd3(p,h,c);
19             for(int k = 0; k <= c; ++k)
20                 for(int j = k * p; j <= n; ++j)
21                     dp[i][j] = max(dp[i][j], dp[i - 1][j - k * p] + k * h);
22         }
23         printf("%d\n",dp[m][n]);
24     }
25     return 0;
26 }

  可以用滚动数组,不过只是得是 dp[2][103] 这样的至少两行数组,而不能是 dp[103] 的一行,因为在读入 p, h, c 后有两个循环的,因此 dp[i-1][j-k*p] 的值就会被多次用到,不能像简单的 01背包、完全背包那样一个循环之后就被会覆盖掉,就是因为这个问题 wa 了好几次,唉,都是模板记得太熟了。

  然后,我看了背包九讲后,发现多重背包还是能作优化的:

  按照他说的我写了下程序,也能AC,代码如下:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define  sd(x)  scanf("%d",&(x))
 6 #define  sd2(x,y)  scanf("%d %d",&(x),&(y))
 7 #define  sd3(x,y,z)  scanf("%d %d %d",&(x),&(y),&(z))
 8 
 9 int dp[103];
10 
11 int main() {
12     int t,n,m,p,h,c;
13     sd(t);
14     while(t--) {
15         sd2(n,m);
16         memset(dp, 0, sizeof(dp));
17         while(m--) {
18             sd3(p,h,c);
19             if(p * c >= n /*&& 0*/) {       // 完全背包这部分其实并不是必须的,一样可以 AC
20                 for(int j = p; j <= n; ++j)
21                     dp[j] = max(dp[j], dp[j - p] + h);
22             }
23             else {
24                 int k = 1;
25                 while(k <= c) {                 // 对转换后的每种物品用 01 背包来实现
26                     for(int j = n; j >= p * k; --j)
27                         dp[j] = max(dp[j], dp[j - p * k] + h * k);
28                     c -= k;
29                     k <<= 1;
30                 }
31                 if(c)                            // 最后作判断一下
32                 for(int j = n; j >= p * c; --j)
33                     dp[j] = max(dp[j], dp[j - p * c] + h * c);
34             }
35         }
36         printf("%d\n",dp[n]);
37     }
38     return 0;
39 }
优化的多重背包
posted @ 2015-07-27 11:27  Newdawn_ALM  阅读(178)  评论(0编辑  收藏  举报