UVa437 The Tower of Babylon

        典型的DAG(有向无环图)最长路模型。本来是DP[a][b],a,b分别表示长和宽,数组存自身加上面最多还能叠多高,但是a,b可能很大,不能开那么大的数组。所以需要转换一下,把立方体的长宽转换为它们的排序,高不用转换。这里利用了set中元素不会重复并自动排序的特性。


#include <iostream>  
#include <stdio.h>  
#include <cmath>  
#include <algorithm>  
#include <iomanip>  
#include <cstdlib>  
#include <string>  
#include <memory.h>  
#include <vector>  
#include <queue>  
#include <stack>  
#include <map>
#include <set>
#include <ctype.h>  
#define INF 1000000

using namespace std;

//转换前 
struct block{
	int x;
	int y;
	int z;
};
block B[40];

//转换后 
struct rect{
	int a;
	int b;
	int h;
};
rect R[100];

int N;
int dp[100][100];

int fun(int s){
	int a=R[s].a;int b=R[s].b;
	if(dp[a][b]!=-1)return dp[a][b];
	int re=0;
	for(int i=1;i<=N*3;i++){
		if( (R[i].a<a&&R[i].b<b)||(R[i].b<a&&R[i].a<b) )re=max(re,fun(i));
	}
	re+=R[s].h;
	dp[a][b]=dp[b][a]=re;
	return re;
}

set<int> rank;

int main(){
	int _case=0;
	while(cin>>N){
		if(!N)break;
		memset(dp,-1,sizeof(dp));
		rank.clear();
		
		for(int i=1;i<=N;i++){
			cin>>B[i].x>>B[i].y>>B[i].z;
			rank.insert(B[i].x);
			rank.insert(B[i].y);
			rank.insert(B[i].z);
		}
		
		for(int i=1;i<=N;i++){
			//找rank
			int rankx,ranky,rankz;
			int count=0;
			for(set<int>::iterator it=rank.begin();it!=rank.end();it++){
				count++;
				if(*it==B[i].x)rankx=count;
				if(*it==B[i].y)ranky=count;
				if(*it==B[i].z)rankz=count;
			}
			//长宽转化为相应的rank 
			R[i*3-2].a=rankx;R[i*3-2].b=ranky;R[i*3-2].h=B[i].z;
			R[i*3-1].a=ranky;R[i*3-1].b=rankz;R[i*3-1].h=B[i].x;
			R[i*3].a=rankz;R[i*3].b=rankx;R[i*3].h=B[i].y;
		}
		
		int _max=0;
		for(int i=1;i<=N*3;i++){
			_max=max(fun(i),_max);
		}
		_case++;
		printf("Case %d: maximum height = %d\n",_case,_max);
	}
	return 0;
}


你可能感兴趣的:(dp,uva)