Space Elevator

            Space Elevator

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

 

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.

题目:

如何建设处最高的塔,注意并不是每一种类型的砖块都垒到它所能达到的最大高度为最优情况

思路:

多重背包

可以进行优化,如下面的二进制压缩,还有单调队列

下面借用背包九讲中的内容,帮助理解一下

二进制优化:将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为 1,2,4,...,2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+1>0的最大整数。例如,如果n[i]为13,就将这种物品分成系数分别为1,2,4,6的四件物品。 
分成的这几件物品的系数和为n[i],表明不可能取多于n[i]件的第i种物品。另外这种方法也能保证对于0..n[i]间的每一个整数,均可以用若干个系数的和表示,这个证明可以分0..2^k-1和2^k..n[i]两段来分别讨论得出

 

# include<iostream>
# include<cstring>
# include<algorithm>
# define max(a,b) a>b?a:b
using namespace std;
struct node
{
    int high;
    int num;
    int mAlti;
}p[1005];
int cmp(struct node a,struct node b)//sort用起来要比qsort简单
{
    return a.mAlti<b.mAlti;
}
int main()
{
    
    int nCase,dp[40005],i,j,k;
        cin>>nCase;
        for(i=1;i<=nCase;i++)
            cin>>p[i].high>>p[i].mAlti>>p[i].num;
        sort(p+1,p+nCase+1,cmp);//排序是从1开始
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        for(i=1;i<=nCase;i++)//二进制压缩
        {
            for(k=1;p[i].num!=0;k*=2)
            {
                if(p[i].num<k)k=p[i].num;
                p[i].num-=k;
                for(j=p[i].mAlti;j>=k*p[i].high;j--)
                {
                    if(dp[j]==0 && dp[j-k*p[i].high])dp[j]=1;//如果h=j-k*p[i].high能垒起,这次就能垒起j的高度
                }
            }
        }
        for(i=p[nCase].mAlti;i>0;i--)
        {
            if(dp[i])  
                break;
        }
        cout<<i<<endl;
    return 0;
} 

 

 

 

 

posted on 2012-08-18 22:37  即为将军  阅读(328)  评论(0)    收藏  举报

导航