NYOJ_矩形嵌套(DAG上的最长路 + 经典dp)
本题大意:给定多个矩形的长和宽,让你判断最多能有几个矩形可以嵌套在一起,嵌套的条件为长和宽分别都小于另一个矩形的长和宽。
本题思路:其实这道题和之前做过的一道模版题数字三角形很相似,大体思路都一致,这道题是很经典的DAG上的最长路问题,用dp[ i ]表示以i为出发点的最长路的长度,因为每一步都只能走向他的相邻点,则
d[ i ] = max(d[ j ] + 1)这里 j 是任意一个面积比 i 小的举行的编号。
下面的代码中附带了最小字典序最长路打印的问题,我们找到第一个路径最长的 i,往后每次都找第一个符合条件的 i 输出即可。
参考代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 << '\t'; 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 }
时间并不会因为你的迷茫和迟疑而停留,就在你看这篇文章的同时,不知道有多少人在冥思苦想,在为算法废寝忘食,不知道有多少人在狂热地拍着代码,不知道又有多少提交一遍又一遍地刷新着OJ的status页面……
没有谁生来就是神牛,而千里之行,始于足下!