继续水DP。应该第一次就AC的,数组开小了,悲剧啊。
摞砖头,砖头的长宽高可以互换。等于说,每个砖头有三种情况,三个底,三个高。
题目要求,砖头可以无限取,但是上面的砖头的底面必须完全包含于下面的砖头的上面。
因为相同长宽的面不可以放一起,所以每种砖头只能取三种情况,也就是三种不同的高。
直接枚举,然后按最小边长排序,然后就和上面那题一样了。
AC搜了下,没啥比较新颖的解法 = =。。而且发现我写的还是比较好看的。。。
#include <queue>
#include <stack>
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define BUG puts("here!!!")
using namespace std;
const int MAX = 35;
struct BLOCK{ int x,y,h;};
BLOCK b[MAX*3];
int dp[MAX*3];
void B(int x,int y,int h,int &cnt)
{
b[cnt].x = min(x,y); b[cnt].y = max(x,y); b[cnt++].h = h;
}
bool check(BLOCK a,BLOCK b)
{
return a.x > b.x && a.y > b.y;
}
bool cmp(BLOCK a,BLOCK b)
{
if( a.x == b.x )
return a.y < b.y;
return a.x < b.x;
}
int main()
{
int n,x,y,z;
int ind = 1;
while( ~scanf("%d",&n) && n )
{
int cnt = 0;
for(int i=0; i<n; i++)
{
scanf("%d%d%d",&x,&y,&z);
B(x,y,z,cnt); B(y,z,x,cnt); B(x,z,y,cnt);
}
sort(b,b+cnt,cmp);
for(int i=0; i<cnt; i++)
dp[i] = b[i].h;
for(int i=1; i<cnt; i++)
for(int k=0; k<i; k++)
if( check(b[i],b[k]) )
dp[i] = max(dp[i],dp[k]+b[i].h);
int ans = dp[max_element(dp,dp+cnt) - dp];
printf("Case %d: maximum height = %d\n",ind++,ans);
}
return 0;
}