题目链接:Monkey and Banana
大意:给出n种箱子的长宽高。每种不限个数。可以堆叠。询问可以达到的最高高度是多少。
要求两个箱子堆叠的时候叠加的面。上面的面的两维长度都严格小于下面的。
简单的DP,依然有很多地发给当时没想到。比如优先级,比如这么简单粗暴的选择。
1 /* 2 大意是。给出n种箱子的长宽高。每种不限个数。可以堆叠。询问可以达到的最高高度是多少。 3 要求两个箱子堆叠的时候叠加的面。上面的面的两维长度都严格小于下面的。 4 5 样例: 6 10 20 30 7 10 20 8 10 30 9 20 30 10 可以摆放的方法:10 20 11 20 30 12 高度: 30+10 = 40 13 14 /思路:把所有种类的箱子的每个面的两维长度都列出来。n<=30,那么,箱子的面个数<=90。然后按照要求来开始堆叠。 15 问题是。我应该怎么来找当前最符合条件的呢。从两维长度都最大的开始吗。下一个怎么对应呢。还是应该从面积最大的开始。可能性太多。 16 以上出自无厘头系列。 17 / 18 19 思路:给出一种箱子可以看做是三个箱子。(完全相同的两个面是不可能出现两次的。所以一个箱子最多会用三次、)。把所有的箱子按照先长后宽,从大到小排序。 20 然后(LIS。求最长递减子序列的思路。)dp[i] = j 表示从1到i的前i个(暂且当做从1开始)箱子里。在选第i个的前提下,得到的最大高度。 21 */ 22 23 #include <stdio.h> 24 #include <string.h> 25 #include <iostream> 26 #include <algorithm> 27 using namespace std; 28 29 struct Node { 30 int x, y, z; 31 }node[2100]; // 最多90个 32 33 bool cmp(Node a, Node b) { 34 if (a.x != b.x) 35 return a.x < b.x; 36 else return a.y < b.y; 37 } 38 39 int h[2100]; 40 41 int main() { 42 int n; 43 int num = 0; 44 while(~scanf("%d", &n)) { 45 if (n == 0) break; 46 num++; 47 for (int j=0, i=0; j<n; ++j) { 48 int a, b, c; 49 scanf("%d%d%d", &a, &b, &c); 50 node[i].x = a, node[i].y = b, node[i].z = c; 51 node[i+1].x = a, node[i+1].y = c, node[i+1].z = b; 52 node[i+2].x = b, node[i+2].y = c, node[i+2].z = a; 53 i += 3; 54 } 55 56 for (int i=0; i<n*3; ++i) { 57 if (node[i].x < node[i].y) { 58 int temp = node[i].y; 59 node[i].y = node[i].x; 60 node[i].x = temp; 61 } 62 } 63 64 sort(node, node+n*3, cmp); 65 int ans = -1; 66 67 for (int i=0; i<3*n; ++i) { 68 h[i] = node[i].z; 69 for (int j=0; j<i; ++j) { 70 if (node[j].x < node[i].x && node[j].y < node[i].y) { 71 h[i] = max(h[i], h[j]+node[i].z); 72 } 73 } 74 ans = max(ans, h[i]); 75 } 76 77 printf("Case %d: maximum height = %d\n", num, ans); 78 } 79 return 0; 80 }