9-2
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstring> #include <algorithm> using namespace std; // 参考 http://blog.csdn.net/u014800748/article/details/43735015 // 题目中的条件是 n 种, 而例题嵌套矩形中的条件是 n 个 // n 种 block 不限供应,也可以将每种block以3种平面为底看成是不同的block,总共 3n 个 block,不限供应 // 如果 a[0] <= a[1] <= a[2], 每种 block 最多用到两个 // if a[0] <= a[1] <= a[2], at most 2 blocks of the same type will be used, the bottom with area a[0] * a[1], and the above with area a[1] * a[2] struct block { int a[3]; // 3 dimensions }; block blockTypes[30]; int n; // n <= 30 int maxiumHeight; // n 种 block,每种 block 3 种底面,数组 d[30][3] 遍历各种情况 int d[30][3]; // d[idx][k] is the maxium height when block of type idx is at the bottom, and the height of block is dimension k // idx is the type number, at most 30 types // k represents the height of the block. each block has 3 dimentions, k may be 0, 1, or 2. int kase = 0; int max(int a, int b) { if (a > b) return a; else return b; } /* compute 2 other dimensions from dimension k k 0 1 2 (k+1)%3 1 2 0 (k+2)%3 2 0 1 a[]是有序的,但这样计算不能保证另两个dimension有序,比如 k == 1 时 下面这种计算方式可以,如果用这种方式,dp(idx,k) 里面的 if(l < w) 和 if(ll < ww) 以及 (l > ww && w > ll) 都可以去掉 k 0 1 2 (2-k)/2 1 0 0 (3-k)/2 + 1 2 2 1 */ // 这里的写法是 记忆化搜索 // 不太好用递归,如果用递归,需要有个计算次序,例题硬币问题里从最小的面值开始计算,例题9-1从最后一站向前计算, 这题里面没有明显的顺序 int dp(int idx, int k) { if (d[idx][k] > 0) // already computed return d[idx][k]; int l = blockTypes[idx].a[(k + 1) % 3]; // length int w = blockTypes[idx].a[(k + 2) % 3]; // width if (l < w){ int tmp = l; l = w; w = tmp; } d[idx][k] = blockTypes[idx].a[k]; // initial value for (int i = 0; i < n; i++){ for (int j = 0; j < 3; j++){ int ll = blockTypes[i].a[(j + 1) % 3]; int ww = blockTypes[i].a[(j + 2) % 3]; if (ll < ww){ int tmp = ll; ll = ww; ww = tmp; } if ((l > ll && w > ww) /*|| (l > ww && w > ll) */) { // 如果去掉上面的 if(l < w) 和 if(ll < ww) 这里的注释要恢复 d[idx][k] = max(d[idx][k], dp(i,j) + blockTypes[idx].a[k]); maxiumHeight = max(maxiumHeight, d[idx][k]); } } } return d[idx][k]; } int main() { while (scanf("%d", &n) && n) { for (int i = 0; i < n; i++) { scanf("%d%d%d", &blockTypes[i].a[0], &blockTypes[i].a[1], &blockTypes[i].a[2]); sort(blockTypes[i].a, blockTypes[i].a + 3); // a[0] <= a[1] <= a[2] } maxiumHeight = 0; memset(d, 0, sizeof(d)); for (int i = 0; i < n; i++){ for (int k = 0; k < 3; k++){ dp(i, k); } } printf("Case %d: maxium height = %d\n", ++kase, maxiumHeight); } return 0; }