题目大意:有n种长方体, 每种有无限个, 要求选一些长方体,摞在一起尽量高,要求上面立方体的长和宽严格小于下面的长方体,每个长方体可以旋转,即每个边都可以做高。
解题思路:每个长方体都有三种状态,即三个楞分别为高的状态,d数组保存每个长方体不同状态时在至最低部能摞最高的高度。记忆化搜索即可,用了一个小技巧,即d(a,b)表示第a个长方体第b条楞为高的状态,用get函数即可求出长和宽。
AC代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
using namespace std;
int block[35][3];
int d[35][3];
int n;
void get(int *v1, int a, int b)
{
int v = 0;
for(int i=0; i<3; i++)
if(i != b) v1[v++] = block[a][i];//获得除高以外的两条楞当作宽和长
}
int dp(int a, int b)
{
if(d[a][b] >= 0) return d[a][b];//已经搜索过
int cur = 0;
int v1[2], v2[2];
get(v1, a, b);
for(int i=0; i < n; i++)
{
for(int j=0; j<3; j++)
{
get(v2, i, j);
if(v1[0] > v2[0] && v1[1] > v2[1])
cur = max(cur, dp(i, j));
}
}
return d[a][b] = cur+block[a][b];
}
int main()
{
int Case = 0;
while(~scanf("%d", &n) && n)
{
int ans = 0;
for(int i=0; i<n; i++)
{
scanf("%d%d%d", &block[i][0], &block[i][1], &block[i][2]);
sort(block[i], block[i]+3);//排序,用于确定长和宽,保证get函数得到的宽小于长
}
memset(d, -1, sizeof(d));
for(int i=0; i<n; i++)
for(int j=0; j<3; j++)
ans = max(ans, dp(i, j));
printf("Case %d: maximum height = %d\n", ++Case, ans);
}
return 0;
}