Monkey and Banana HDU - 1069
题意:
有n种类型的砖块,每种类型的砖块都有无限个。第i块砖块的长宽高分别用xi,yi,zi来表示。 同时,由于砖块是可以旋转的,每个砖块的3条边可以组成6种不同的长宽高。
在构建塔时,当且仅当A砖块的长和宽都分别小于B砖块的长和宽时,A砖块才能放到B砖块的上面。
问最高可以堆出的砖块们的高度
题解:
我们设dp[i]表示以i个砖是最下面的砖块时,可以达到的最大高度
我们先存下每个砖的六个状态(即长宽高互相换位置),然后按照长和宽从小到大排序,排序后,对于j<i,若第j个砖的长和宽均小于i,则第j个砖是可以放在i的上面的
对于第i个砖,以第i个砖为底的最大值就是dp[i]=h[i]+max(dp[j]),j<i,且第j个砖的长和宽均小于i,也就是把之前的砖为底的最大值放在第i个砖的上面
这个题的本质就是最长上升子序列
代码:
#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\n",a,b);
typedef long long ll;
using namespace std;inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w;
}
const int maxn=1e5+9;
struct node{int l,s,h;node(int l,int s,int h):l(l),s(s),h(h){}bool operator <(const node &c)const{if(l==c.l)return s<c.s;return l<c.l;}
};
vector<node>v;
int dp[maxn];
int main()
{int n;int tot=0;while(cin>>n){if(n==0)break;v.clear();memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++){int l,s,h;cin>>l>>s>>h;v.push_back(node(l,s,h));v.push_back(node(l,h,s));v.push_back(node(s,l,h));v.push_back(node(s,h,l));v.push_back(node(h,s,l));v.push_back(node(h,l,s));}sort(v.begin(),v.end());int maxx=0;for(int i=0;i<v.size();i++){dp[i]=v[i].h;for(int j=i-1;j>=0;j--){if(v[j].l<v[i].l&&v[j].s<v[i].s&&dp[j]+v[i].h>dp[i]){dp[i]=dp[j]+v[i].h;}}maxx=max(dp[i],maxx);}printf("Case %d: maximum height = %d\n",++tot,maxx);}
}