DAG上的动态规划---嵌套矩形(模板题)
一、DAG的介绍
Directed Acyclic Graph,简称DAG,即有向无环图,有向说明有方向,无环表示不能直接或间接的指向自己。
摘录:有向无环图的动态规划是学习动态规划的基础,很多问题都可以转化为DAG上的最长路、最短路或路径计数问题。
通常需要建图,不复杂的也可以当最长上升子序列处理,就不必建图,但都包含运用有向无环图的思想。
二、例题
有n(1 <= n <= 1000)个矩形,长为a,宽为b。矩形X(a,b)可以嵌套在矩形Y(c,d)中,当且仅当a < c,b < d,或者a < d,b < c。求最大的嵌套数。
三、解题思路
矩形X可以嵌套矩形Y,则从X连条边到Y,矩形不能直接或间接的嵌套自己,所以无环。最大的嵌套次数,就是求这个图上的最长路。
四、代码实现
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdbool> 5 #include<vector> 6 #include<algorithm> 7 using namespace std; 8 9 const int maxn = 1000 + 10; 10 struct Node 11 { 12 int x, y; 13 Node(int x, int y) :x(x), y(y) {} 14 Node() {} 15 bool operator < (const Node &n)const { 16 return (x < n.x&& y < n.y) || (x < n.y&& y < n.x); 17 } 18 }; 19 vector<Node>vec; 20 int n; 21 int d[maxn]; //d[i]表示从节点i出发的最长路的长度 22 bool G[maxn][maxn]; 23 int cnt = 0; 24 25 //建图 26 void creatGraph() 27 { 28 for (int i = 0; i < n; i++) 29 for (int j = 0; j < n; j++) 30 { 31 if (vec[i] < vec[j]) G[i][j] = true; 32 } 33 } 34 35 //计算从i出发的最长路径 36 int dp(int i) 37 { 38 int& ans = d[i]; 39 if (ans > 0) return ans; 40 ans = 1; 41 for (int j = 0; j < n; j++) 42 if (G[i][j]) ans = max(ans, dp(j) + 1); 43 return ans; 44 } 45 46 //解决问题 47 void slove() 48 { 49 creatGraph(); 50 int res = 0; 51 for (int i = 0; i < n; i++) 52 res = max(res, dp(i)); //整体的时间复杂度为O(n^2) 53 54 printf("Case %d: maximum = %d\n", ++cnt, res); 55 } 56 int main() 57 { 58 while (scanf("%d", &n) == 1 && n) 59 { 60 vec.clear(); 61 memset(d, 0, sizeof(d)); 62 memset(G, false, sizeof(G)); 63 int x, y; 64 for (int i = 0; i < n; i++) 65 { 66 scanf("%d%d", &x, &y); 67 vec.push_back(Node(x, y)); 68 } 69 slove(); 70 } 71 }
当然,这题也可以用最长上升子序列做,可以参考我的前一篇博客。
个性签名:时间会解决一切