input:
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
output:
Case 1: maximum height = 40
Case 2: maximum height = 21
Case 3: maximum height = 28
Case 4: maximum height = 342
题目大意:
有n种方块(x,y,z三个属性),每种可以用无数次。要求上方的方块底面边长要都小于下面方块底面的边长,求用
这n块方块最多能搭多高。
分析:
最长上升子序列。一块方块有6种摆法,所以事先将6种摆法放入数组,并按照底面边长从小到大排序。dp[j]=前i
个最顶上为j方块的高度。
code:
#define frp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f;
const ll inf = 0x7fffff;
const int maxn = 1e8;
const int MAXN = 10000;
int n;
struct node {
int x, y, z;
bool operator<(const node &a) const {
return x == a.x ? y < a.y : x < a.x;
}
} block[MAXN];
int dp[MAXN];
void solve() {
int t = 1;
while (cin >> n && n) {
int cnt = 0;
int x, y, z;
for (int i = 0; i < n; i++) {
cin >> x >> y >> z;
block[cnt++] = {x, y, z};
block[cnt++] = {x, z, y};
block[cnt++] = {y, x, z};
block[cnt++] = {y, z, x};
block[cnt++] = {z, x, y};
block[cnt++] = {z, y, x};
}
int ans = 0;
sort(block, block + cnt);
for (int i = 0; i < cnt; i++) {
dp[i] = block[i].z;
for (int j = 0; j < i; j++) {
if (block[j].x < block[i].x && block[j].y < block[i].y) {
dp[i] = max(dp[j] + block[i].z, dp[i]);
}
}
ans = max(ans, dp[i]);
}
cout << "Case " << t++ << ": maximum height = " << ans << endl;
}
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef frp
freopen("D:\\coding\\c_coding\\in.txt", "r", stdin);
// freopen("D:\\coding\\c_coding\\out.txt", "w", stdout);
#endif
solve();
return 0;
}