uva 437

来源:互联网 发布:网络拓扑visio图库 编辑:程序博客网 时间:2024/05/29 04:44

题目概述:

用砖堆柱子,有kind种砖,每种砖都是长方体,长宽高分别为x,y,z,同一种砖的三个参数可以互换位置,最底层(地面)可放任意砖,但只有底面的长和宽(前两个参数)分别小于下层的,才可以放在下层的砖上面,并将这块砖的高(第三个参数)加到柱子的高度中

输入:

第一行kind,其后kind行每行x,y,z,多组数据之间没有空行,输入以0为一行结束

限制:

0<n<=30

输出:

每行一个字符串,若用%times%表示第times组数据(times从1开始),%ans%表示可以堆成的最高的柱子的高度,则字符串为

Case %times%: maximum height = %ans%

注意冒号右侧有空格,等号左右均有空格,%ans%后无空格

样例输入:

1

10 20 30

2

6 8 10

5 5 5

7

1 1 1

2 2 2

3 3 3

4 4 4

5 5 5

6 6 6

7 7 7

5

31 41 59

26 53 58

97 93 23

84 62 64

33 83 27

0

样例输出:

Case 1: maximum height = 40

Case 2: maximum height = 21

Case 3: maximum height = 28

Case 4: maximum height = 342

讨论:

这个题的一个小难点在于如何高效存储砖的数据,一个比较低效的实现是每种砖存一次,利用函数(或成员函数)在一砖砖内部三个参数互换后进行比较

从抽象模型上,可以视为有向无环的节点加权图,也可以看做简单的递归,但无论如何,着实有记忆化的思想

1.这里将每种砖的三个参数分别左移(不是<<运算符)一次,作为三种砖存储,由于check函数可以检查前两个参数互换的情况,因而少存了三次,也因此n只有30,而数组开到100


题解状态:

0 KB,0 ms,C++11 4.8.2,1383

#include<cmath>#include<cctype>#include<cstring>#include<algorithm>#include<cstdio>#include<numeric>#include<vector>#include<set>#include<map>#include<queue>#include<list>#include<stack>using namespace std;struct node{int x;int y;int z;};node nodes[100];//用于存放每种砖的数据int kind;//由于深搜需要知晓种数,为方便作为全局变量int mem[100];//memory,存放从nodes中某种砖开始深搜所得最优解inline bool ck(node &a, node &b)//check,检查是否能将一块砖放在另一块上方,可以检查长宽互换后的情况{return (a.x > b.x&&a.y > b.y) || (a.x > b.y&&a.y > b.x);}inline int maxx(int a, int b)//专用的max函数,敲了很多次,已经很熟练了{return a > b ? a : b;}int dfs(node &a, int b)//深搜,第二个参数是砖a在nodes里的序号,在迭代时一并传递,作为mem数组下标{int biggest = 0;//初始化深搜所得最优解为0for (int p = 0; p < 3 * kind; p++) {//选择一块要放在上方的砖,因此深搜最深的砖是底面长宽最小的那个if ((ck(a, nodes[p]))) {//判断能否放在上方if (mem[p] != -1) {biggest = maxx(biggest, mem[p]);//最优解已知,直接返回结果} else {biggest = maxx(biggest, dfs(nodes[p], p));//最优解未知,深搜}}}mem[b] = biggest + a.z;//退出深搜前将最优解记录return mem[b];//返回上层深搜}int fun(int kind){for (int p = 0; p < kind; p++) {int x, y, z;scanf("%d%d%d", &x, &y, &z);//inputnodes[p].x = x, nodes[p].y = y, nodes[p].z = z;nodes[p + kind].y = x, nodes[p + kind].z = y, nodes[p + kind].x = z;nodes[p + 2 * kind].z = x, nodes[p + 2 * kind].x = y, nodes[p + 2 * kind].y = z;//参见讨论1}int biggest = 0;//初始化最大值for (int p = 0; p < 3*kind; p++) {//从所有点开始深搜,由于深搜过一次后便在mem数组留下记录,因此多数深搜只是去读个数就返回biggest = maxx(biggest, dfs(nodes[p], p));}return biggest;}int main(void){//freopen("vs_cin.txt", "r", stdin);int times = 0;//记数据序号while (~scanf("%d", &kind) && kind) {//inputmemset(mem, -1, sizeof(mem));printf("Case %d: maximum height = %d\n", ++times, fun(kind));//output}}

EOF

0 0
原创粉丝点击