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 }

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

转载于:https://www.cnblogs.com/lfri/p/9444356.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值