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 }

 当然,这题也可以用最长上升子序列做,可以参考我的前一篇博客。

posted @ 2018-08-08 17:55  Rogn  阅读(611)  评论(0编辑  收藏  举报