
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;
}