最长上升子序列(矩形嵌套)
问题一:
矩形嵌套问题: 给定n个矩形,每个矩形有个长和宽,只有当一个矩形的长宽小于另外一个矩形的长宽时,才能嵌套在另外一个矩形内部。求出尽量多的矩形排成一行,嵌套的矩形数目最多。
这个问题其实就是求最长上升子序列,只不过比较大小的时候变成了比较两个变量。
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 1003; struct rect { int l, w; bool operator < (const rect &b) const { return w < b.w && l < b.l; } }; bool cmp(const rect &a, const rect &b) { if (a.l != b.l) return a.l < b.l; return a.w < b.w; } rect r[maxn]; int dp[maxn]; int main() { int T, n; cin >> T; while (T--) { cin >> n; for (int i = 0; i < n; i++) { cin >> r[i].l >> r[i].w; if (r[i].l < r[i].w) swap(r[i].l, r[i].w); dp[i] = 1; } sort(r, r + n, cmp); int ans = 1; for (int i = 1; i < n; i++) { for (int j = 0; j < i; j++) { if (r[j] < r[i] && dp[i] < dp[j] + 1) { dp[i] = dp[j] + 1; } } ans = max(ans, dp[i]); } printf("%d\n", ans); } return 0; }
问题二:
巴比伦塔: 给定n个立方体,求出选一些立方体摞成一个尽量高的柱子,要求每个立方体底面的长宽必须严格小于他下方的立方体的长宽。
这个问题稍微一转化也是最长上升子序列,只不过是把输入的立方体看成三种立方体就行了。比较大小的时候同样比较的是长和宽。具体代码如下:
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 100; struct rect { int l, w, h; bool operator < (const rect &b) const { return (l < b.l && w < b.w); } void f(int a, int b, int c) { l = a; w = b; h = c; } void exchange() { if (l < w) swap(l, w); } }; rect r[maxn]; int dp[maxn]; bool cmp(const rect &a, const rect &b) { if (a.l == b.l) return a.w > b.w; return a.l > b.l; } int main() { int n, kase = 0; while (~scanf("%d", &n) && n) { int a, b, c, cnt = 0; rect tmp; for (int i = 0; i < n; i++) { scanf("%d %d %d", &a, &b, &c);//将这个立方体分别转化成三个立方体,高度分别为a, b, c tmp.f(a, b, c); tmp.exchange(); r[cnt++] = tmp; tmp.f(a, c, b); tmp.exchange(); r[cnt++] = tmp; tmp.f(b, c, a); tmp.exchange(); r[cnt++] = tmp; } sort(r, r + cnt, cmp); memset(dp, 0, sizeof(dp)); int ans = 0; for (int i = 0; i < cnt; i++)//最长子序列 { dp[i] = r[i].h; for (int j = 0; j < i; j++) { if (r[i] < r[j]) dp[i] = max(dp[i], dp[j] + r[i].h); } ans = max(ans, dp[i]); } printf("Case %d: maximum height = %d\n", ++kase, ans); } return 0; }