Space Elevator
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 10506 | Accepted: 4994 |
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.
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.
* 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.
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.
Source
USACO 2005 March Gold
求用这些砖叠在一起的最大高度。
①多重部分和;
②多重背包,限制高度作为背包中的最大高度。
两种方法解题占用内存一样,但是①比②快一倍。
AC代码①多重部分和
AC代码②多重背包
题目意思:
有K组数,后面三个数h,a,c分别表示一块砖的高度、用这种砖的最大高度和用这种砖的最多块数。求用这些砖叠在一起的最大高度。
解题思路:
用结构体根据“用这种砖的最大高度”升序排列,然后有两种思路:①多重部分和;
②多重背包,限制高度作为背包中的最大高度。
两种方法解题占用内存一样,但是①比②快一倍。
AC代码①多重部分和
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100010
int dp[MAXN];//d[i]表示石块能组成的高度为i
struct Node
{
int h,a,c;//分别表示一块砖的高度、用这种砖的最大高度和最多块数
} s[MAXN];
int cmp(Node x,Node y)//结构体排序
{
return x.a<y.a;//升序
}
int main()
{
int n,i,j,ans=0;
cin>>n;
for(i=0; i<n; ++i)
cin>>s[i].h>>s[i].a>>s[i].c;
sort(s,s+n,cmp);//按最大高度升序排列
memset(dp,-1,sizeof dp);
dp[0]=0;
for(i=0; i<n; i++)//多重部分和
for(j=0; j<=s[i].a; j++)
{
if (dp[j]>=0) dp[j]=s[i].c;
else if (j<s[i].h || dp[j-s[i].h] <=0) dp[j]=-1;
else dp[j] = dp[j-s[i].h]-1;
}
for (i=s[n-1].a; i>=0; --i)
if(dp[i]>=0)
{
ans=i;
break;
}
cout<<ans<<endl;
return 0;
}
AC代码②多重背包
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100010//一开始开了10010一直RE…囧o(╯□╰)o
int dp[MAXN];//d[i]表示石块能组成的高度为i
struct Node
{
int h,a,c;//分别表示一块砖的高度、用这种砖的最大高度和最多块数
} s[MAXN];
int cmp(Node x,Node y)//结构体排序
{
return x.a<y.a;//升序
}
int main()
{
int n,i,j,k,ans=0;
cin>>n;
for(i=0; i<n; ++i)
cin>>s[i].h>>s[i].a>>s[i].c;
sort(s,s+n,cmp);//按最大高度升序排列
memset(dp,0,sizeof(dp));//初始化
for(i=0; i<n; ++i)//n种砖块,使用多重背包
{
if(s[i].h*s[i].c>=s[i].a)//完全背包
for(j=s[i].h; j<=s[i].a; j++)
dp[j]=max(dp[j],dp[j-s[i].h]+s[i].h);
else//01背包
{
for(k=1; k<=s[i].c; k<<=1) //数量
{
for(j=s[i].a; j>=k*s[i].h; --j)//高度
dp[j]=max(dp[j],dp[j-k*s[i].h]+k*s[i].h);
s[i].c-=k;//减去用过的数量
}
for(j=s[i].a; j>=s[i].h*s[i].c; --j)
dp[j]=max(dp[j],dp[j-s[i].h*s[i].c]+s[i].h*s[i].c);
}
}
for(i=1; i<=s[n-1].a; ++i)//s[n-1].a表示所有限制高度中的最大值
ans=max(ans,dp[i]);//找出石块能组成的最大高度
cout<<ans<<endl;
return 0;
}