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