题目链接:
http://poj.org/problem?id=2392
题意:
给你k类方块,每类方块ci个,每类方块的高度为hi,现在要报所有的方块叠在一起,每类方块的任何一个部分都不能出现在ai以上的高度,问这些方块能叠的最高高度。
题解:
首先按ai升序排序,尽量让高度限制低的先排掉,如果不这样做一些转移会失效掉:
比如:h1=3,a1=3;h2=4,a2=7
如果先搭1再搭2则合法,但反过来则变成无效的转移了。
处理好顺序之后跑一遍背包就可以了,因为最大高度为40000,比较小,所以用判定的方式跑一遍就可以了。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 6 using namespace std; 7 8 const int maxn = 40000 + 40; 9 const int maxm = 444; 10 11 int k; 12 int dp[maxn],used[maxn]; 13 int hi[maxm], ai[maxm], ci[maxm]; 14 15 int ran[maxm]; 16 bool cmp(int x,int y) { 17 return ai[x] < ai[y]; 18 } 19 20 void init() { 21 memset(dp, 0, sizeof(dp)); 22 for (int i = 0; i < k; i++) ran[i] = i; 23 } 24 25 int main() { 26 while (scanf("%d", &k) == 1 && k) { 27 init(); 28 for (int i = 0; i < k; i++) { 29 scanf("%d%d%d", hi + i, ai + i, ci + i); 30 } 31 sort(ran, ran + k,cmp); 32 dp[0] = 1; 33 for (int i = 0; i < k; i++) { 34 int t = ran[i]; 35 memset(used, 0, sizeof(used)); 36 for (int h = hi[t]; h <= ai[t]; h++) { 37 //dp[h]==0一定也要记得写,这里也是个贪心 38 if (dp[h]==0&&dp[h - hi[t]] && used[h - hi[t]] + 1 <= ci[t]) { 39 dp[h] = 1; used[h] = used[h - hi[t]] + 1; 40 } 41 } 42 } 43 int ans = 0; 44 for (int i = 40000; i >= 0; i--) if (dp[i]) { 45 ans = i; break; 46 } 47 printf("%d\n", ans); 48 } 49 return 0; 50 }
总结:
这题和经典的多重背包问题还是有些差别的:
这题是求给定一系列元素的高度,个数,高度限制,求最大高度。
而经典多重背包问题是给定一系列元素的价值,体积,体积限制,求最大价值。