题意描述:有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. 元数据和DbUtils

    使用元数据可以在jdbc中获取数据库的定义,例如:数据库.表.列的定义信息. 在jdbc中可以使用: 数据库元数据.参数元数据.结果集元数据. 1.DataBaseMetaData对象 Connect ...

  2. [vijos P1112] 小胖的奇偶

    第一次看到这题怎么也不会想到是并查集题目…星期五第一次看到这题,到今天做出来,实在是废了好多功夫.看了很多人的解题都有same和diff数组,我也写了,后来发现不对啊两个数组的话find函数怎么写呢? ...

  3. 统计一段文字中出现频率最高的10个单词(c语言)

    注:这次使用C语言做的这个程序.个别不懂的地方和算法部分是请教的其他同学,交流并吸收,所以收获颇多! 在程序中每一个地方我都做了注释,方便同学之间交流.也让老师容易看.程序也有很多不足的地方,但限于本 ...

  4. protected 和default的区别

    default:包内可见,包外不可见 protected:包内可见,包外不可见,但是包外继承之后可见.

  5. hadoop启动之后出现错误:Retrying connect to server: hadoop/192.168.73.100:9000. Already tried 0 time(s);

    INFO ipc.Client: Retrying connect to server: hadoop/192.168.73.100:9000. Already tried 0 time(s); re ...

  6. SimpleDateFormat格式化日期

    SimpleDateFormat格式化日期 import java.text.SimpleDateFormat;import java.util.Date;public class test { pu ...

  7. poj2631 树的直径 + bfs

    //Accepted 492 KB 0 ms //树的直径 bfs #include <cstdio> #include <cstring> #include <iost ...

  8. Cobub Razor

    Cobub Razor - 开源移动应用统计分析平台

  9. STL源码分析《4》----Traits技术

    在 STL 源码中,到处可见 Traits 的身影,其实 Traits 不是一种语法,更确切地说是一种技术. STL库中,有一个函数叫做 advance, 用来将某个迭代器(具有指针行为的一种 cla ...

  10. mac上安装MySQL

    mysql 官网下载http://dev.mysql.com/downloads/mysql/ 注意安装mysql-5.5.17-osx10.6-x86_64.dmg这样安装方便设置系统安全权限后 点 ...