uva 437

题目概述:

用砖堆柱子,有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;//初始化深搜所得最优解为0
	for (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);//input
		nodes[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) {//input
		memset(mem, -1, sizeof(mem));
		printf("Case %d: maximum height = %d\n", ++times, fun(kind));//output
	}
}

EOF

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值