思路完全模仿lrj白书。
25题斩。
具体而言,我们发现两个矩形之间是包含关系,比如说A包含于B,我们可以认为,A可以推出B,同理若B可以推出C,则A也可以推出C。
这就好像是一个DAG,于是本题转化成了求DAG上的最长路问题。
我们只需要对于每一个点都dp一下就好了。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1005; int t, n; struct node { int x, y; }a[maxn]; int g[maxn][maxn], vis[maxn], d[maxn]; int dp(int x) { int& ans = d[x];//经典套路,最后ans的值将自动代入d[x] if (vis[x]) return d[x];//记忆化搜索,表示已经搜过了。 vis[x] = 1; ans = 1; for (int i = 1; i <= n; i++) if (g[x][i]) ans = max(ans, dp(i) + 1); return ans; } void print_ans(int x) { printf("%d ", x); for (int j = 1; j <= n; j++) if(g[x][j] && d[x] == d[j] + 1) { print_ans(j); break;//字典序最小。 } } void solve() { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d%d", &a[i].x, &a[i].y); if (a[i].x > a[i].y) swap(a[i].x, a[i].y); } memset(g, 0, sizeof g); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) if(a[i].x < a[j].x && a[i].y < a[j].y) { g[i][j] = 1; } int mx = 0; memset(d, 0, sizeof d); memset(vis, 0, sizeof vis); int jl; for (int i = 1; i <= n; i++) if (!vis[i]) { int t = dp(i); if (t > mx) { mx = t; jl = i; } } printf("%d ", mx); print_ans(jl); } int main() { scanf("%d", &t); while (t--) solve(); return 0; }