ZOJ_1903 Monkey and Banana

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;
}





你可能感兴趣的:(ZOJ_1903 Monkey and Banana)