NYOJ_矩形嵌套(DAG上的最长路 + 经典dp)

  本题大意:给定多个矩形的长和宽,让你判断最多能有几个矩形可以嵌套在一起,嵌套的条件为长和宽分别都小于另一个矩形的长和宽。

  本题思路:其实这道题和之前做过的一道模版题数字三角形很相似,大体思路都一致,这道题是很经典的DAG上的最长路问题,用dp[ i ]表示以i为出发点的最长路的长度,因为每一步都只能走向他的相邻点,则

d[ i ]  = max(d[ j ] + 1)这里 j 是任意一个面积比 i 小的举行的编号。

  下面的代码中附带了最小字典序最长路打印的问题,我们找到第一个路径最长的 i,往后每次都找第一个符合条件的 i 输出即可。

  参考代码:

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 typedef pair<int ,int > P;
 6 int n, m;
 7 const int maxn = 100 + 5, Max = 1000 + 5;
 8 int G[maxn][maxn], cnt, b;
 9 int d[maxn];
10 P rectangle[Max];
11 
12 bool check(int i, int j) {
13     return (rectangle[i].first > rectangle[j].first && rectangle[i].second > rectangle[j].second) || 
14         (rectangle[i].first > rectangle[j].second && rectangle[i].second > rectangle[j].first);
15 }
16 
17 int dp(int i) {
18     int &ans = d[i];
19     if(ans != -1) return ans;
20     ans = 1;
21     for(int j = 0; j < maxn; j ++)
22         if(G[i][j] == 1) ans = max(ans, dp(j) + 1);
23     cnt = max(cnt, ans);
24     return ans;
25 }
26 
27 void print_ans(int i) {
28     cout << i << '	';
29     for(int j = 0; j < maxn; j ++)
30         if(G[i][j] == 1 && d[i] == d[j] + 1) {
31             print_ans(j);
32             break;
33         }
34 }
35 
36 int main () {
37     int n;
38     cin >> n;
39     while(n --) {
40         cnt = 0;
41         memset(d, -1, sizeof d);
42         memset(G, -1, sizeof G);
43         cin >> m;
44         for(int i = 0; i < m; i ++)
45             cin >> rectangle[i].first >> rectangle[i].second;
46         for(int i = 0; i < m; i ++)
47             for(int j = 0; j < m; j ++)
48                 if(check(i, j))
49                     G[i][j] = 1;
50         for(int i = 0; i < m; i ++)
51             dp(i);
52         cout << cnt << endl;
53         for(int i = 0; i < maxn; i ++) if(d[i] == cnt) b = i;
54         // print_ans(b);
55     }
56     return 0;
57 }
View Code
原文地址:https://www.cnblogs.com/bianjunting/p/10599390.html