UVA437
在这里插入图片描述
一种砖块的三个边都可以当作高度,因此n中砖块对应有3n中搭砖方式。
定义:dp[i]为一第i中方式为底的最大高度,blocks[i]为第i中搭砖方式。
初始化:dp[i]=0,即什么也不放。
转移方程

1
2
3
4
5
6
7
8
9
10
11
12
int DFS(int Node) {
if (dp[Node]) {//如果当前节点已经被搜索过,就直接返回。
return dp[Node];
}
dp[Node] = blocks[Node].z;//对应只放当前方式的高度
for (int i = 1; i <= 3 * n; ++i) {//枚举每种搭建方式
if (blocks[Node].Fit(blocks[i])) {//如果第i种方式能放在第Node种上
dp[Node] = max(dp[Node], DFS(i) + blocks[Node].z);//Node放在最底层,然后上面放i的最大高度
}
}
return dp[Node];
}

AC代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n, dp[91];
struct Block {
int x, y, z;
bool Fit(const Block& UpperBlock)const {
return
UpperBlock.x < x && UpperBlock.y < y
||
UpperBlock.y < x && UpperBlock.x < y;
}
}blocks[91];
bool Input() {
cin >> n;
if (!n) {
return false;
}
for (int i = 1; i <= 3 * n; i += 3) {
int x, y, z;
cin >> x >> y >> z;
//每条边都可以作为高,以z为高
blocks[i] = Block{ x,y,z };
blocks[i+1] = Block{ x,z,y };
blocks[i+2] = Block{ y,z,x };
}
return true;
}
int DFS(int Node) {
if (dp[Node]) {
return dp[Node];
}
dp[Node] = blocks[Node].z;
for (int i = 1; i <= 3 * n; ++i) {
if (blocks[Node].Fit(blocks[i])) {
dp[Node] = max(dp[Node], DFS(i) + blocks[Node].z);
}
}
return dp[Node];
}
int DP() {
memset(dp, 0x0, sizeof(dp));
int&& Ans = 0;
//枚举以所有方式为最底层的高度。
for (int i = 1; i <= 3 * n; ++i) {
Ans = max(Ans, DFS(i));
}
return Ans;
}
int main() {
int Case = 0;
while (Input()) {
printf("Case %d: maximum height = %d\n", ++Case, DP());
}
return 0;
}

*PS
:递归真香