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 ...
随机推荐
- Section 1.4 Mother's Milk
又是一道怨念已久的题目0 0之前深搜写过广搜写过,怎么就是卡死,我还以为FP坏了重新装了一遍.今天偶尔翻起来,发现广搜忘记inc(head)了…简直哭瞎… 简单的广搜,分类比较多,不过不太要动脑子.至 ...
- Matlab与C/C++联合编程之Matlab以MEX方式调用C/C++代码(一)
MEX文件是一种可在matlab环境中调用的C语言(或fortran)衍生程序,mex的编译结果实际上就是一个带输出函数mexFunction 的dll文件. 中文名 mex文件 外文名 MATLAB ...
- SharePoint 2013 开发——SharePoint Designer 2013工作流
博客地址:http://blog.csdn.net/FoxDave SharePoint Designer 2013为开发者和高级用户提供了两种创建定制工作流的模式: 基于文本的设计器--即我们一直 ...
- 立体透视 perspective transform-style 倾斜旋转
1.perspective 是设置镜头距离,距离越远视图越小,视图越近,视图越大.就像相机焦距一样.其只对子元素产生效果. 2.transform-style: preserve-3d 设置3d效果, ...
- python 绘图工具 matplotlib 入门
转自: http://www.cnblogs.com/kaituorensheng/p/3440273.html matplotlib 是python最著名的绘图库,它提供了一整套和matlab相似的 ...
- Javascript 基础(一)
一.Js命名规范(变量/函数) (1)使用大小写字母,数字,_ ,$ 可以命名 (2)不能以数字打头 (3)不能使用js的关键字/保留字 (4)区分大小写 (5)单行注释 //多行注释 二.js的数据 ...
- 关于struts2拦截器获取页面参数
package InterCeptor; import java.util.Iterator;import java.util.Map;import java.util.Map.Entry;impor ...
- 字符串常量演示Demo
public class StringDemo { public static void main(String[] args) { // TODO Auto-generated method stu ...
- C#获取项目程序及运行路径的方法
1.asp.net webform用“Request.PhysicalApplicationPath获取站点所在虚拟目录的物理路径,最后包含“\”: 2.c# winform用 A:“Applicat ...
- 解密SQL SERVER 2005加密存储过程,函数
在SQL SERVER 2005中必须用专用管理连接才可以查看过程过程中用到的表 EG:sqlcmd -A 1>use test 2>go 1>sp_decrypt 'p_testa ...