POJ 2392 Space Elevator 贪心+dp

题目链接:

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
", ans);
48     }
49     return 0;
50 }

总结:

这题和经典的多重背包问题还是有些差别的:

这题是求给定一系列元素的高度,个数,高度限制,求最大高度。

而经典多重背包问题是给定一系列元素的价值,体积,体积限制,求最大价值。

原文地址:https://www.cnblogs.com/fenice/p/5461467.html