1 条题解
-
0
解题思路
1. 问题转化
由于积木可以旋转,我们需要枚举每个积木的所有可能摆放方式。对于一个尺寸为
(x, y, z)
的积木,可以有以下 6 种摆放方式(3 种底面 × 2 种高度方向):(x, y, z)
(底面x × y
,高度z
)(x, z, y)
(底面x × z
,高度y
)(y, x, z)
(底面y × x
,高度z
)(y, z, x)
(底面y × z
,高度x
)(z, x, y)
(底面z × x
,高度y
)(z, y, x)
(底面z × y
,高度x
)
2. 排序优化
为了便于动态规划计算,我们需要对所有可能的积木块进行排序:
- 按长
x
降序排序,如果x
相同,则按y
降序排序。 - 这样,在动态规划时,可以确保较大的积木先处理,避免重复计算。
3. 动态规划
定义
dp[i]
表示以第i
个积木为顶时的最大高度。状态转移方程为: [ dp[i] = \text{max}(dp[j] + \text{height}_i) \quad \text{其中} \quad x_j > x_i \quad \text{且} \quad y_j > y_i ] 即,遍历所有j < i
的积木,找到可以放在i
下面的积木j
,并更新dp[i]
。4. 最终答案
最终答案就是所有
dp[i]
中的最大值。C++实现
#include <iostream> #include <vector> #include <algorithm> using namespace std; struct Block { int x, y, z; Block(int a, int b, int c) : x(a), y(b), z(c) {} bool operator<(const Block& other) const { if (x != other.x) return x > other.x; // 按 x 降序 return y > other.y; // x 相同时按 y 降序 } }; int main() { int n, caseNum = 0; while (cin >> n && n != 0) { caseNum++; vector<Block> blocks; // 生成所有可能的积木摆放方式(6种) for (int i = 0; i < n; i++) { int x, y, z; cin >> x >> y >> z; blocks.push_back(Block(x, y, z)); blocks.push_back(Block(x, z, y)); blocks.push_back(Block(y, x, z)); blocks.push_back(Block(y, z, x)); blocks.push_back(Block(z, x, y)); blocks.push_back(Block(z, y, x)); } // 按 x 和 y 降序排序 sort(blocks.begin(), blocks.end()); // DP: dp[i] 表示以第 i 个积木为顶的最大高度 vector<int> dp(blocks.size()); int maxHeight = 0; for (int i = 0; i < blocks.size(); i++) { dp[i] = blocks[i].z; // 初始高度是当前积木的高度 for (int j = 0; j < i; j++) { if (blocks[j].x > blocks[i].x && blocks[j].y > blocks[i].y) { dp[i] = max(dp[i], dp[j] + blocks[i].z); } } maxHeight = max(maxHeight, dp[i]); } cout << "Case " << caseNum << ": maximum height = " << maxHeight << endl; } return 0; }
- 1
信息
- ID
- 1242
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 5
- 已通过
- 1
- 上传者