引例:NYOJ16

矩形嵌套

时间限制:3000 ms  |           内存限制:65535 KB
难度:4
 
描述
有n个矩形,每个矩形可以用a,b来描述,表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。

 
输入
第一行是一个正正数N(0<N<10),表示测试数据组数,
每组测试数据的第一行是一个正正数n,表示该组测试数据中含有矩形的个数(n<=1000)
随后的n行,每行有两个数a,b(0<a,b<100),表示矩形的长和宽
输出
每组测试数据都输出一个数,表示最多符合条件的矩形数目,每组输出占一行
样例输入
  1. 1
  2. 10
  3. 1 2
  4. 2 4
  5. 5 8
  6. 6 10
  7. 7 9
  8. 3 1
  9. 5 8
  10. 12 10
  11. 9 7
  12. 2 2
样例输出
  1. 5
  2.  
  3. 我们可以这样建模:将每个矩形视作一个结点,若矩形A能覆盖矩形B,那么就在作一条结点A指向结点B的有向路径,结果我们会得到一个DAG(有向无环图)。求符合条件的最多矩形数目,就是DAG中最长路径上的结点数目。
    DAG上的最长路径上的结点数目,我们可用记忆化搜索求解,(同poj1088滑雪)
    代码如下:
  1. #include<cstdio>
  2. #include<cstring>
  3. #include<vector>
  4. #include<algorithm>
  5. using namespace std;
  6. const int MAXN=;
  7. vector<int> G[MAXN];
  8. int V,E;
  9. int d[MAXN];
  10. int dfs(int u)
  11. {
  12. if(d[u]>) return d[u];
  13. int ans=;
  14. for(int i=;i<G[u].size();i++)
  15. {
  16. ans=max(ans,dfs(G[u][i])+);
  17. }
  18. return d[u]=ans;
  19. }
  20. int main()
  21. {
  22. memset(d,,sizeof(d));
  23. scanf("%d%d",&V,&E);
  24. for(int i=;i<E;i++)
  25. {
  26. int u,v;
  27. scanf("%d%d",&u,&v);
  28. G[u].push_back(v);
  29. }
  30. int ans=;
  31. for(int i=;i<=V;i++)
  32. ans=max(ans,dfs(i));
  33. printf("%d\n",ans+);
  34. return ;
  35. }
  36. /*
  37. 7 8
  38. 1 2
  39. 1 3
  40. 3 2
  41. 2 4
  42. 2 5
  43. 4 6
  44. 6 5
  45. 5 7
  46.  
  47. 7
  48. */

这样 矩形覆盖问题就迎刃而解。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<vector>
  4. #include<algorithm>
  5. using namespace std;
  6. const int MAXN=;
  7. vector<int> G[MAXN];
  8. struct Rect{
  9. int x,y;
  10. }rect[MAXN];
  11. int n;
  12. void createG()
  13. {
  14. for(int i=;i<=n;i++)
  15. for(int j=;j<=n;j++)
  16. if((rect[i].x<rect[j].x&&rect[i].y<rect[j].y)||(rect[i].y<rect[j].x&&rect[i].x<rect[j].y))
  17. {
  18. G[j].push_back(i);
  19. }
  20. }
  21. int d[MAXN];
  22. int dfs(int u)
  23. {
  24. if(d[u]>) return d[u];
  25. int ans=;
  26. for(int i=;i<G[u].size();i++)
  27. ans=max(ans,dfs(G[u][i])+);
  28. return d[u]=ans;
  29. }
  30. int main()
  31. {
  32. int T;
  33. scanf("%d",&T);
  34. while(T--)
  35. {
  36. scanf("%d",&n);
  37. for(int i=;i<=n;i++)
  38. {
  39. G[i].clear();
  40. scanf("%d%d",&rect[i].x,&rect[i].y);
  41. }
  42. createG();
  43. memset(d,,sizeof(d));
  44. int ans=;
  45. for(int i=;i<=n;i++)
  46. ans=max(ans,dfs(i));
  47. printf("%d\n",ans+);
  48. }
  49.  
  50. return ;
  51. }

该问题也可以转化为最长上升子序列问题求解。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. const int INF=;
  6. struct Rect{
  7. int x,y;
  8. }rect[];
  9. int n;
  10. bool comp(const Rect &a,const Rect &b)
  11. {
  12. if(a.x==b.x) return a.y > b.y;//µ±±ß³¤ÏàͬʱÓдóµ½Ð¡ÅÅÐò
  13. else return a.x < b.x;
  14. }
  15. int dp[];
  16. int main()
  17. {
  18. int T;
  19. scanf("%d",&T);
  20. while(T--)
  21. {
  22. scanf("%d",&n);
  23. for(int i=;i<n;i++)
  24. {
  25. scanf("%d%d",&rect[i].x,&rect[i].y);
  26. dp[i]=INF;
  27. }
  28. sort(rect,rect+n,comp);
  29. for(int i=;i<n;i++)
  30. *lower_bound(dp,dp+n,rect[i].y)=rect[i].y;
  31. printf("%d\n",lower_bound(dp,dp+n,INF)-dp);
  32. }
  33.  
  34. return ;
  35. }

DAG上的DP的更多相关文章

  1. UVA - 10131Is Bigger Smarter?(DAG上的DP)

    题目:UVA - 10131Is Bigger Smarter? (DAG) 题目大意:给出一群大象的体重和IQ.要求挑选最多的大象,组成一个序列.严格的体重递增,IQ递减的序列.输出最多的大象数目和 ...

  2. BZOJ 3998 TJOI2015 弦论 后缀自动机+DAG上的dp

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3998 题意概述:对于一个给定长度为N的字符串,求它的第K小子串是什么,T为0则表示不同位置 ...

  3. NYOJ16 矩形嵌套 【DAG上的DP/LIS】

    矩形嵌套 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c ...

  4. UVA 10917 Walk Through the Forest(dijkstra+DAG上的dp)

    用新模板阿姨了一天,换成原来的一遍就ac了= = 题意很重要..最关键的一句话是说:若走A->B这条边,必然是d[B]<d[A],d[]数组保存的是各点到终点的最短路. 所以先做dij,由 ...

  5. BZOJ 4011 HNOI2015 落忆枫音 DAG上的dp(实际上重点在于分析)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4011 题意概述:给出一张N点的DAG(从1可以到达所有的点),点1的入度为0.现在加一条原 ...

  6. UVA 11324 The Largest Clique(缩点+DAG上的dp)

    求最大团.和等价性证明有类似之处,只不过这个不是求互推,而是只要a->b,或b->a即可. 同样的,容易想到先缩点,得到DAG,每个节点上保存SCC的点数,相信任意一条由根节点(入度为零) ...

  7. Codeforces 919D Substring ( 拓扑排序 && DAG上的DP )

    题意 : 给出含有 N 个点 M 条边的图(可能不连通或者包含环),每个点都标有一个小写字母编号,然后问你有没有一条路径使得路径上重复字母个数最多的次数是多少次,例如图上有条路径的顶点标号顺序是  a ...

  8. (板子)缩点 + DAG上的DP(深搜)luogu P3387

    板子传送门 根据题目意思,我们只需要找出一条点权最大的路径就行了,不限制点的个数.那么考虑对于一个环上的点被选择了,一整条环是不是应该都被选择,这一定很优,能选干嘛不选.很关键的是题目还允许我们重复经 ...

  9. UVa1025 (DAG上的dp)

    这是紫书上的第一个dp哈. 1.状态定义:dp[i][j]---->到时刻i的时候(出发的时候时刻为0,约定时间为时刻time),从j号车站开往N号车站,在车站等待的最少的时间. 2.这个人当前 ...

随机推荐

  1. C 标准库 - <stddef.h>

    C 标准库 - <stddef.h> 简介 stddef .h 头文件定义了各种变量类型和宏.这些定义中的大部分也出现在其它头文件中. 库变量 下面是头文件 stddef.h 中定义的变量 ...

  2. 最新研发的基于Java的高速开发平台

    可自我扩展的智能开发平台       在开发平台设计过程中,联科研发部一開始就希望能研发一套智能开发机制能自己开发自己的平台-即一个能自我修复和自我扩展的开发平台.这个开发平台不但能开发其它应用还能不 ...

  3. [GUIDE] How to Setup Ubuntu 16.04 LTS Xenial Xerus for Compiling Android ROMs

    With a new version of Ubuntu comes an update to my guide for setting up a build environment to compi ...

  4. C# 之 集合ArrayList

    .NET Framework提供了用于数据存储和检索的专用类,这些类统称集合. 这些类提供对堆栈.队列.列表和哈希表的支持.大多数集合类实现系统的接口.以下我们主要来讲一下ArrayList.     ...

  5. TensorFlow从入门到实战资料汇总 2017-02-02 06:08 | 数据派

    TensorFlow从入门到实战资料汇总 2017-02-02 06:08 | 数据派 来源:DataCastle数据城堡 TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学 ...

  6. Linux 操作系统中的进程结构

    前言 在 Linux 中,一个正在执行的程序往往由各种各样的进程组成,这些进程除了父子关系,还有其他的关系.依赖于这些关系,所有进程构成一个整体,给用户提供完整的服务( 考虑到了终端,即与用户的交互 ...

  7. android arcmenu

    http://www.kankanews.com/ICkengine/archives/129193.shtml

  8. 设置netbeans文件编码格式

    在项目ecmall上右键 选择属性,然后在项目属性里设置

  9. 【BZOJ2521】[Shoi2010]最小生成树 最小割

    [BZOJ2521][Shoi2010]最小生成树 Description Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算 ...

  10. javascript JSON.parse和eval的区别

    SON.parse()用来将标准json字符串转换成js对象:eval()除了可以将json字符串(非标准的也可以,没有JSON.parse()要求严格)转换成js对象外还能用来动态执行js代码.例如 ...