DAG上的动态规划之嵌套矩形
题意描述:有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上的动态规划之嵌套矩形的更多相关文章
- UVa 103 Stacking Boxes --- DAG上的动态规划
UVa 103 题目大意:给定n个箱子,每个箱子有m个维度, 一个箱子可以嵌套在另一个箱子中当且仅当该箱子的所有的维度大小全部小于另一个箱子的相应维度, (注意箱子可以旋转,即箱子维度可以互换),求最 ...
- 第九章(二)DAG上的动态规划
DAG上的动态规划: 有向无环图上的动态规划是学习DP的基础,很多问题都可以转化为DAG上的最长路.最短路或路径计数问题. 1.没有明确固定起点重点的DAG模型: 嵌套矩形问题:有n个矩形,每个矩形可 ...
- UVA 1025 "A Spy in the Metro " (DAG上的动态规划?? or 背包问题??)
传送门 参考资料: [1]:算法竞赛入门经典:第九章 DAG上的动态规划 题意: Algorithm城市的地铁有 n 个站台,编号为 1~n,共有 M1+M2 辆列车驶过: 其中 M1 辆列车从 1 ...
- 嵌套矩形——DAG上的动态规划
有向无环图(DAG,Directed Acyclic Graph)上的动态规划是学习动态规划的基础.非常多问题都能够转化为DAG上的最长路.最短路或路径计数问题. 题目描写叙述: 有n个矩形,每一个矩 ...
- DAG上的动态规划---嵌套矩形(模板题)
一.DAG的介绍 Directed Acyclic Graph,简称DAG,即有向无环图,有向说明有方向,无环表示不能直接或间接的指向自己. 摘录:有向无环图的动态规划是学习动态规划的基础,很多问题都 ...
- DAG 上的动态规划(训练指南—大白书)
有向无环图(DAG,Directed Acyclic Graph)上的动态规划是学习动态规划的基础.很多问题都可以转化为DAG上的最长路.最短路或路径计数问题. 一.矩形嵌套 题目描述: ...
- DP入门(2)——DAG上的动态规划
有向无环图(DAG,Directed Acyclic Graph)上的动态规划是学习动态规划的基础.很多问题都可以转化为DAG上的最长路.最短路或路径计数问题. 一.DAG模型 [嵌套矩形问题] 问题 ...
- 9.2 DAG上的动态规划
在有向无环图上的动态规划是学习动态规划的基础,很多问题都可以转化为DAG上的最长路,最短路或路径计数问题 9.2.1 DAG模型 嵌套矩形问题: 矩形之间的可嵌套关系是一种典型的二元关系,二元关系可以 ...
- DAG上的动态规划
嵌套矩形问题(最长路及其字典序)有n个举行,选出尽量多的矩阵排成一排,使得除了最后一个之外,每一个矩形可以嵌套在下一个矩形内,并且打印 #include <iostream> #inclu ...
随机推荐
- Spring与Hibernate整合,实现Hibernate事务管理
1.所需的jar包 连接池/数据库驱动包 Hibernate相关jar Spring 核心包(5个) Spring aop 包(4个) spring-orm-3.2.5.RELEASE.jar ...
- S5PV210之添加缺少的-内核提供的'.h'文件 linux3.0.8驱动
怎样解决编译时出现内核提供的函数或变量没有定义,使用source insight搜索功能找到声明的头文件,然后包含该头件就行了: 比如: error: implicit declaration of ...
- 使用变量替换批量部署GoldenGate
GoldenGate运行时允许在参数文件中动态指定一个值,即在参数文件中使用一个变量,而不是一个静态的值,当启动OGG进程时,根据环境动态加载此变量的值,达到在不同环境中,通过变量定义,实现多个环境的 ...
- 如何在ubuntu 12.04 中安装经典的 GNOME桌面
这次介绍的是如何在ubuntu 12.04 中安装经典的 GNOME桌面,默认的 Ubuntu 12.04 默认unity桌面,一些用户不喜欢 Unity 桌面,所以想找回昔日的经典Gnome桌面. ...
- coreData旧版本增加字段,新版本是否可以继续使用旧版本内容的测试(MagicalRecord的使用)
coreData使用第三方库MagicalRecord, 参考文章:http://blog.csdn.net/kuizhang1/article/details/21200367 coreData数据 ...
- VMware与Cisco etherchannel
命令样例: ①把要绑定team的端口添加到channel-group interface Te2/1/1 switchport switchport access vlan 123 switchpor ...
- Editplus 正则表达式 删除含有指定字符串的行 删除注释
1.删除含有指定字符串的行 替换: ^.*(指定字符串).*$ 为空 例如,删除含有"JOIN"的行, 替换: ^.*JOIN.*$ 为空 2.删除//行注释 替换: / ...
- HDU 5800 (DP)
Problem To My Girlfriend (HDU 5800) 题目大意 给定一个由n个元素组成的序列,和s (n<=1000,s<=1000) 求 : f (i,j,k,l, ...
- mysql的ERROR:1042
在虚拟机上测试数据库备份功能,需要连接外部机器上的mysql,pdo总是报超时错误! 起初认为是用的mysql账号的域不匹配!后来发现不是因为这个! 在终端中用mysql命令尝试连接,发现返回的错误是 ...
- busybox inetd tftpd
/*************************************************************************** * busybox inetd tftpd * ...