zoukankan      html  css  js  c++  java
  • 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
    ", ++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 }

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

  • 相关阅读:
    在oracle中通过connect by prior来实现递归查询!
    c# System.Data.OracleClient需要Oracle客户端软件8.1.7或更高版本
    c# 水晶报表的设计(非常的基础)
    webapi+EF(增删改查)
    简单三层分页aspnetpager控件(欢迎指点)
    listbox 多选删除(找了好多都不行,终于让我写出来了)
    execl导出(HTML,repearter控件)
    SQL Server中截取字符串常用函数
    几个经常用到的字符串的截取
    gridview的增删改
  • 原文地址:https://www.cnblogs.com/lfri/p/9444356.html
Copyright © 2011-2022 走看看