第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > POJ 2392 Space Elevator(多重背包变形)

POJ 2392 Space Elevator(多重背包变形)

时间:2022-02-15 03:09:02

相关推荐

POJ 2392 Space Elevator(多重背包变形)

Q: 额外添加了最大高度限制, 需要根据 alt 对数据进行预处理么?

A: 是的, 需要根据 alt 对数组排序

Description

The cows are going to space! They plan to achieve orbit by building a sort of space elevator: a giant tower of blocks. They have K (1 <= K <= 400) different types of blocks with which to build the tower. Each block of type i has height h_i (1 <= h_i <= 100) and is available in quantity c_i (1 <= c_i <= 10). Due to possible damage caused by cosmic rays, no part of a block of type i can exceed a maximum altitude a_i (1 <= a_i <= 40000).

Help the cows build the tallest space elevator possible by stacking blocks on top of each other according to the rules.

Input

* Line 1: A single integer, K

* Lines 2..K+1: Each line contains three space-separated integers: h_i, a_i, and c_i. Line i+1 describes block type i.

Output

* Line 1: A single integer H, the maximum height of a tower that can be built

Sample Input

37 40 35 23 82 52 6

Sample Output

48

Hint

OUTPUT DETAILS:

From the bottom: 3 blocks of type 2, below 3 of type 1, below 6 of type 3. Stacking 4 blocks of type 2 and 3 of type 1 is not legal, since the top of the last type 1 block would exceed height 40.

思路:

对数据预处理, 按照 alt 排序预处理, 倍增优化, 转化成 01 背包求解 01 背包

总结:

1. 对 3 个数组, 以其中一个为根据排序, 一种解决方法是把三个数组绑定到一个对象中, 然后对对象排序

2. 犯了个致命的错误, 48行代码写成memset(dp, 0, sizeof(int)*V); 导致当 V 比较大时, h 也被置 0 了

代码:

#include <iostream>#include <algorithm>using namespace std;int K;const int MAXN = 40010;bool dp[40010];int h[MAXN], a[MAXN];int V;struct block {int h, a, c;bool operator<(const block &other) const {return this->a < other.a;}};block blocks[MAXN];int pre_process() {sort(blocks, blocks+K);int len = 0;for(int i = 0; i < K; i ++) {int rem = blocks[i].c;int j = 0;// 预处理, while(rem) {if(rem >= (1<<j)) {h[len] = (1<<j)*blocks[i].h;a[len] = blocks[i].a;rem -= (1<<j);j++;if(h[len] > a[len])continue;len++;}else{h[len] = rem*blocks[i].h;a[len] = blocks[i].a;len++;rem = 0;}}}return len;}int solve_dp() {int len = pre_process();// 01背包memset(dp, 0, sizeof(dp));dp[0] = 1;for(int i = 0; i < len; i ++) {for(int v = V; v >= h[i]; v--) {if(v > a[i]) continue;if(!dp[v] && dp[v-h[i]]) {dp[v] = true;//printf("dp[%d] = true\n", v);}}}for(int v = V; v >= 0; v --)if(dp[v])return v;}int main() {freopen("E:\\Copy\\ACM\\测试用例\\in.txt", "r", stdin);cin >> K;int h_i, a_i, c_i;V = 0;for(int i = 0; i < K; i ++) {scanf("%d%d%d", &blocks[i].h, &blocks[i].a, &blocks[i].c);V = min(V+blocks[i].h*blocks[i].c, 40000);}cout << solve_dp() << endl;return 0;}

update: 3月14日10:35:10

1. 贪心策略是最大高度较小的先放

Q1: 对物品排序会对结果产生影响吗

A1: 会的. 假设只有两个物品, 最大高度不同, 显然最大高度较小的放前面可以获摆放的更高

Q2: 第二层循环, V 是怎么初始化的

A2: 上面的代码初始化比较随意, V 初始化为 40000 和 所有梯子高度之和 的较小值

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。