题意描述:有n个矩形,每个矩形可以用两个整数a、b描述,表示它的长和宽,

       矩形(a,b)可以嵌套在矩形(c,d)当且仅当a<c且b<d,

       要求选出尽量多的矩形排成一排,使得除了最后一个外,

       每一个矩形都可以嵌套在下一个矩形内,如果有多解,矩形编号的字典序应尽量小

  解题思路:<1>矩形之间的可嵌套关系是一个"二元关系",二元关系可以用图来建模。

       如果矩形X可以嵌套在矩形Y里,就从X到Y连一条有向边(G[x][y]=1)。

       这个图是无环的,因为一个矩形无法直接或间接地嵌套在自己内部,

       换句话说,他是一个DAG。

       这样,原问题便转化为求DAG上的最长路径。

       <2>那么如何求DAG最长上的最长路径呢?

         可定义状态: dp[i]表示从结点i出发所能到达的最长路径的长度

         那么: dp[i] = max(dp[j]) + 1, 其中G[i][j]=1,即i可嵌套在j中

         最后数组d中的最大值便是结果

       <3>如何保证最小字典序?

         在所有的d都计算出来以后,选择最大的d[i]所对应的i。

         如果有多个i,选择最小的i。(i即第一个起点)

         接下来可以选择d[i] = d[j]+1且(i,j)为边集的任何一个j,

         但为了保证字典序最小,应该选择其中最小的j,

/* DAG上的动态规划之嵌套矩形 */
#include <cstdio>
#include <cstring> const int maxn = ;
int n, G[maxn][maxn];
int a[maxn], b[maxn];
int dp[maxn]; void swap(int &x, int &y){
x ^= y;
y ^= x;
x ^= y;
} //将x和y的最大值存在x中
inline void CMAX(int& x, int y){
if (y > x){
x = y;
}
} /* 采用记忆化搜索 求从s能到达的最长路径 */
int DP(int s){
int& ans = dp[s];
if (ans > )
//记忆化搜索,避免重复计算
return ans;
ans = ;
for (int j = ; j <= n; ++j){
if (G[s][j]){
//sj有边 利用子问题dp[j]+1更新最大值
CMAX(ans, DP(j) + );
}
}
return ans;
} void print_ans(int i){
printf("%d ", i);
for (int j = ; j <= n; ++j){
if (G[i][j] && dp[j] + == dp[i]){
print_ans(j);
break;
}
}//for(j)
} int main()
{
#ifdef _LOCAL
freopen("D:\\input.txt", "r", stdin);
#endif
while (scanf("%d", &n) == ){
//n个矩形
for (int i = ; i <= n; ++i){
//默认a存长,b存宽(a > b)
scanf("%d%d", a + i, b + i);
if (a[i] < b[i]){
swap(a[i], b[i]);
}
}
/*
建图 G[i][j]为1表示矩形i可以嵌套在矩形j中
那么原问题便转化为求DAG上的最长路径 定义状态dp[i]表示从结点i出发可以到达的最长路径
则 dp[i] = max(dp[j] + 1), 其中 G[i][j]=1,
*/
memset(G, , sizeof G);
for (int i = ; i <= n; ++i){
for (int j = ; j <= n; ++j){
//矩形i的长和宽都小于矩形j的长和宽
if (a[i] < a[j] && b[i] < b[j]){
G[i][j] = ; //可以嵌套,则有边
}
}
}//for(i)
memset(dp, , sizeof dp);
int ans = ;
int best;
for (int i = ; i <= n; ++i){
if (DP(i) > ans){
ans = dp[i];
best = i;
}
}//for(i)
printf("ans = %d\n", ans);
print_ans(best);
printf("\n");
}
return ;
}

  解题思路2:如果只需要求得最多可以嵌套多少个矩形,而不要求输出序列,

        定义一个结构体,内含有变量a,b,输入时保证a>b(a为长,b为宽)

        对a进行排序,最后求b的最长上升子序列(状态转移时要加上A[j].a<A[i].a的条件)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = ;
int dp[maxn]; struct Node{
int a, b;
bool operator<(Node& other){
if (a != other.a){
return a < other.a;
}
else{
return b < other.b;
}
}
}A[maxn]; void SWAP(int& x, int& y){
x ^= y;
y ^= x;
x ^= y;
} void CMAX(int& x, int y){
if (y > x){
x = y;
}
} int main()
{
#ifdef _LOCAL
freopen("D:\\input.txt", "r", stdin);
#endif int n;
while (scanf("%d", &n) == ){
for (int i = ; i <= n; ++i){
//a为长,b为宽
scanf("%d%d", &A[i].a, &A[i].b);
if (A[i].a < A[i].b){
SWAP(A[i].a, A[i].b);
}
dp[i] = ;
}//for(i)
sort(A + , A + n + );
//求b的最长上升子序列
int ans = ;
int best = ;
dp[] = ;
for (int i = ; i <= n; ++i){
for (int j = ; j < i; ++j){
if (A[j].a < A[i].a && A[j].b < A[i].b){
CMAX(dp[i], dp[j] + );
}
}
if (dp[i] > ans){
ans = dp[i];
best = i;
}
//CMAX(ans, dp[i]);
} printf("ans = %d\n", ans);
} return ;
}

DAG上的动态规划之嵌套矩形的更多相关文章

  1. UVa 103 Stacking Boxes --- DAG上的动态规划

    UVa 103 题目大意:给定n个箱子,每个箱子有m个维度, 一个箱子可以嵌套在另一个箱子中当且仅当该箱子的所有的维度大小全部小于另一个箱子的相应维度, (注意箱子可以旋转,即箱子维度可以互换),求最 ...

  2. 第九章(二)DAG上的动态规划

    DAG上的动态规划: 有向无环图上的动态规划是学习DP的基础,很多问题都可以转化为DAG上的最长路.最短路或路径计数问题. 1.没有明确固定起点重点的DAG模型: 嵌套矩形问题:有n个矩形,每个矩形可 ...

  3. UVA 1025 "A Spy in the Metro " (DAG上的动态规划?? or 背包问题??)

    传送门 参考资料: [1]:算法竞赛入门经典:第九章 DAG上的动态规划 题意: Algorithm城市的地铁有 n 个站台,编号为 1~n,共有 M1+M2 辆列车驶过: 其中 M1 辆列车从 1 ...

  4. 嵌套矩形——DAG上的动态规划

    有向无环图(DAG,Directed Acyclic Graph)上的动态规划是学习动态规划的基础.非常多问题都能够转化为DAG上的最长路.最短路或路径计数问题. 题目描写叙述: 有n个矩形,每一个矩 ...

  5. DAG上的动态规划---嵌套矩形(模板题)

    一.DAG的介绍 Directed Acyclic Graph,简称DAG,即有向无环图,有向说明有方向,无环表示不能直接或间接的指向自己. 摘录:有向无环图的动态规划是学习动态规划的基础,很多问题都 ...

  6. DAG 上的动态规划(训练指南—大白书)

    有向无环图(DAG,Directed Acyclic Graph)上的动态规划是学习动态规划的基础.很多问题都可以转化为DAG上的最长路.最短路或路径计数问题. 一.矩形嵌套 题目描述:       ...

  7. DP入门(2)——DAG上的动态规划

    有向无环图(DAG,Directed Acyclic Graph)上的动态规划是学习动态规划的基础.很多问题都可以转化为DAG上的最长路.最短路或路径计数问题. 一.DAG模型 [嵌套矩形问题] 问题 ...

  8. 9.2 DAG上的动态规划

    在有向无环图上的动态规划是学习动态规划的基础,很多问题都可以转化为DAG上的最长路,最短路或路径计数问题 9.2.1 DAG模型 嵌套矩形问题: 矩形之间的可嵌套关系是一种典型的二元关系,二元关系可以 ...

  9. DAG上的动态规划

    嵌套矩形问题(最长路及其字典序)有n个举行,选出尽量多的矩阵排成一排,使得除了最后一个之外,每一个矩形可以嵌套在下一个矩形内,并且打印 #include <iostream> #inclu ...

随机推荐

  1. FCKEditor文件上传提示信息的汉化

    FCKEditor文件上传提示信息的汉化在FCKeditor中,虽然可以自动监测客户端语言,但是仍有小部分信息未能得到汉化.例如上传图片.Flash时,上传成功和上传失败的对话框提示信息均为英文,只要 ...

  2. ios 学习 广告图片轮播器

    // // ViewController.m // 图片轮播器 // // Created by zjj on 15/5/23. // Copyright (c) 2015年 zjj. All rig ...

  3. Android 系统基础

    当系统启动一个组件,它其实就启动了这个程序的进程(如果这个进程还未被启动的话)并实例化这个组件所需要的类. 例如,如果你的程序启动了相机程序里的activity去拍照,这个activity实际上是运行 ...

  4. julia生成指定格式的字符串.jl

    julia生成指定格式的字符串.jl """ julia生成指定格式的字符串.jl http://bbs.bathome.net/thread-39829-1-1.htm ...

  5. php中的include()的使用技巧

    php中的include()的使用技巧 include() 语句包括并运行指定文件. 以下文档也适用于 require().这两种结构除了在如何处理失败之外完全一样.include() 产生一个警告而 ...

  6. C语言学习笔记之成员数组和指针

    成员数组和指针是我们c语言中一个非常重要的知识点,记得以前在大学时老师一直要我们做这类的练习了,但是最的还是忘记了,今天来恶补一下.     单看这文章的标题,你可能会觉得好像没什么意思.你先别下这个 ...

  7. 技术分享:逆向分析ATM分离器

    文章内容仅供技术交流,请勿模仿操作! 背景(作者) 每一次外出时, Elizabeth和我总是格外的小心,同时把我们身上的钱藏在特殊的皮带上面,这样还不够,我们还采取了“狡兔三窟”的方式来藏身上带的银 ...

  8. 文件IO和标准IO

    2015.2.26 星期四,阴天 今天的内容主要是文件IO man 手册的分册: man -f open 查看那些分册中有openman 1 -- 普通的命令程序man 2 -- 系统调用man 3 ...

  9. ACDream-C - Transformers' Mission(Dijastra最短路径)

    dijstra求最短路径:经典应用题目: 题意:给你一个带权值无向图,权值是A点到B点的时间,然后告诉你起点,一个人可以去炸掉一个结点或多个节点,也可以派多个人,最终这些人在终点集合,问最后一个到达终 ...

  10. MonogoDB的GirdFS

    GirdFS是一种在MongoDB中存储大二进制文件的机制. mongofiles内置在MongoDB发布版中,可以用来在GridFS中上传.下载.列示.查找或删除文件. $ echo "H ...