http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1093
题目大意:给定一些block,每个block都有一定的尺寸,x,y,z,每种block都有无数个,求用这些block能搭成的最大高度,要求在上面的block的base面的大小都要严格小于其下面block的base面的大小。
算法: DP,最大下降子序列;
分析:我们可以用下面的视觉来看待这个问题,每个block分为x,y,z,且没个block都是固定的,也就是说,如果这个block被选中,则其高度就为z。这样考虑的话,每种block最多就会被用6块,将所有的block都存起来,用sort函数进行排序,以x递减为第一序,y为二序排序。在排序完的数组中进行DP,求最长下降子序列 。
代码:
/*
Name: ZOJ_1093
Algorithm: DP + 最长下降子序列;
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define max(a,b) (a>b?a:b)
using namespace std;
int n,x,y,z;
struct Node{
int x,y,z ;
friend bool operator <(const Node& a,const Node& b)
{
if(a.x == b.x) return a.y < b.y ;
else return a.x < b.x ;
}
}block[31*6] ;
int dp[31*6] ;
int main()
{
int cnt ,ncase = 1;
//freopen("1in.txt","r",stdin);
//freopen("1out.txt","w",stdout);
while(scanf("%d",&n) && n)
{
cnt = 0;
for(int i=0;i<n;i++)
{
scanf("%d %d %d",&x,&y,&z);
int tx = x , ty = y , tz = z ;
block[cnt].x = tx ; block[cnt].y = ty ; block[cnt].z = tz ; cnt++ ;
block[cnt].x = ty ; block[cnt].y = tx ; block[cnt].z = tz ; cnt++ ;
block[cnt].x = tx ; block[cnt].y = tz ; block[cnt].z = ty ; cnt++ ;
block[cnt].x = ty ; block[cnt].y = tz ; block[cnt].z = tx ; cnt++ ;
block[cnt].x = tz ; block[cnt].y = ty ; block[cnt].z = tx ; cnt++ ;
block[cnt].x = tz ; block[cnt].y = tx ; block[cnt].z = ty ; cnt++ ;
}
sort(block,block+6*n);
dp[0] = block[0].z ;
int max_ = dp[0] ;
for(int i=1;i<6*n;i++)
{
int MAX_ = 0 ;
for(int j=i-1;j>=0;j--)
{
if(block[i].x == block[j].x || block[i].y <= block[j].y)
continue ;
MAX_ = max(MAX_,dp[j]) ;
}
dp[i] = MAX_ + block[i].z ;
max_ = max(max_,dp[i]) ;
}
printf("Case %d: maximum height = ",ncase);
ncase ++ ;
printf("%d\n",max_);
}
return 0;
}