zoukankan      html  css  js  c++  java
  • 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

    3
    7 40 3
    5 23 8
    2 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.
     

    思路:

    1. 对数据预处理, 按照 alt 排序
    2. 预处理, 倍增优化, 转化成 01 背包
    3. 求解 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
    ", 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: 2014年3月14日10:35:10

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

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

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

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

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

  • 相关阅读:
    JAVA程序员面试之《葵花宝典》
    61条Java面向对象设计的经验原则
    悟透JavaScript
    61条Java面向对象设计的经验原则
    悟透JavaScript
    SQL与Oracle数据库镜像对比
    21条SQL Server数据库开发经验
    VB开发——复制Excell表格
    国外Web2.0介绍
    关于RSS
  • 原文地址:https://www.cnblogs.com/xinsheng/p/3463863.html
Copyright © 2011-2022 走看看