继续水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; }