有向无环图上的动态规划是学习动态规划的基础,很多问题都可以转化为DAG上的最长路、最短路或路径计数问题。

嵌套矩阵

  有n个矩阵,每个矩阵可以用两个整数a,b描述,表示它的长和宽。矩阵X(a,b)可以嵌套在矩阵Y(c,d)中当且仅当a<c,b<d,或者b<c,a<d(相当于把矩阵X旋转90)例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)内。你的任务是选出尽量多的矩阵排成一行,使得除了最后一个只之外,每一个矩形都可以嵌套在下一个矩形内。

分析:

  矩阵之间的“可嵌套”关系是一个典型的二元关系,二元关系可以用图来建模。如果矩形X可以嵌套在矩形Y里,我们就从X到Y连一条有向边,这个图是无环的,因为一个矩形无法直接或者间接地嵌套在自己内部。换句话说,它是一个DAG,我们的任务便是求DAG上的最长路径。

  设d(i)表示从结点i 出发的最长路长度。第一步只能到它的相邻点,d(i) = max{d(j)+1|(i,j)属于E},其中E是边集。最终答案是所有d(i)中的最大值。假设用邻接矩阵保存在矩阵G中。

记忆化搜索代码如下:

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define maxn 1000
using namespace std;
int G[maxn][maxn], a[maxn], b[maxn], d[maxn], n, answer;
int dp(int i)
{
int& ans = d[i];
if (ans > ) return ans;
ans = ;
for(int j = ; j <= n; ++j) if(G[i][j]) ans = max(ans, dp(j)+);
return ans;
}
void print_ans(int i)
{
printf("%d(%d, %d) ", i, a[i], b[i]);
for(int j = ; j <= n; ++j) if(G[i][j] && d[j]+ == d[i])
{
print_ans(j);
break;
}
} int path[maxn] = {}, cnt = ;
void print_all(int i)
{
//输出所有符合条件的路径
path[++cnt] = i;
if(cnt == answer)
{
for(int j = ; j <= cnt; ++j) printf("%d(%d, %d) ", path[j], a[path[j]], b[path[j]]);
printf("\n");
}
else for(int j = ; j <= n; ++j) if(G[i][j] && d[j]+ == d[i])
{
print_all(j);
}
--cnt;
}
/*
//作者的方法
int path[maxn];
void print_all(int cur, int i) {
path[cur] = i;
if(d[i] == 1) {
for(int j = 0; j <= cur; j++) printf("%d ", path[j]);
printf("\n");
}
for(int j = 1; j <= n; j++) if(G[i][j] && d[i] == d[j]+1)
print_all(cur+1, j);
}
*/
int main()
{
freopen("9-2.in", "r", stdin);
scanf("%d", &n);
for(int i = ; i <= n; ++i) scanf("%d%d", a+i, b+i);
memset(G, , sizeof(G));
for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j) if((a[i]>a[j]&&b[i]>b[j])||(a[i]>b[j]&&b[i]>a[j]))
G[i][j] = ;
int t, s;
answer = -;
memset(d, , sizeof(d));
for (int i = ; i <= n; ++i)
{
t = dp(i);
if(answer < t)
{
answer = t;
s = i;
}
}
printf("%d\n", answer);
print_ans(s);
printf("\nAll routes:\n");
//print_all(0, s);
print_all(s);
return ;
}

另一代码如下:

 //另附0ms     236kb的DP思路:按边长降序排序,用类似LIS的方法求解,只是比较元素大小的方法变成了比较长和宽
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define maxn 1008
using namespace std;
int G[maxn][maxn], a[maxn], b[maxn], d[maxn], n;
int dp(int i)
{
int& ans = d[i];
if (ans > ) return ans;
ans = ;
for(int j = ; j <= n; ++j) if(G[i][j]) ans = max(ans, dp(j)+);
return ans;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i = ; i <= n; ++i) scanf("%d%d", a+i, b+i);
memset(G, , sizeof(G));
for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j) if((a[i]>a[j]&&b[i]>b[j])||(a[i]>b[j]&&b[i]>a[j]))
G[i][j] = ;
int ans = -, t, s;
memset(d, , sizeof(d));
for (int i = ; i <= n; ++i)
{
t = dp(i);
if(ans < t)
{
ans = t;
s = i;
}
}
printf("%d\n", ans);
}
return ;
}

DAG模型——嵌套矩阵的更多相关文章

  1. NYOJ16|嵌套矩形|DP|DAG模型|记忆化搜索

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

  2. UVA103 dp基础题,DAG模型

    1.UVA103 嵌套n维空间 DAG模型记忆化搜索,或者 最长上升子序列. 2.dp[i]=max( dp[j]+1),(第i个小于第j个) (1) //DAG模型记忆化搜索 #include< ...

  3. WEBGL学习【四】模型视图矩阵

    <html lang="zh-CN"> <!--服务器运行地址:http://127.0.0.1:8080/webgl/LearnNeHeWebGL/NeHeWe ...

  4. OpenGL(五) 三维变换之模型视图矩阵

    计算机三维图形学中,一个基本的任务是如何描述三维空间中一个物体位置的变化,也就是如何 描述物体的运动.通常情况下,物体位置的变化包含三个基本的变化:平移.旋转和缩放,物体的运动也可以用这三个基本的运动 ...

  5. HDU 1588 矩阵快速幂 嵌套矩阵

    这个题目搞了我差不多一个下午,之前自己推出一个公式,即 f[n+k]=k*f[n]+f[n-1]结果发现根本不能用,无法降低复杂度. 后来又个博客的做法相当叼,就按他的做法来了 即 最终求得是 S(n ...

  6. DAG上的动态规划——嵌套矩阵问题

    问题描述:有n个矩形,每个矩形可以用两个整数a,b描述,表示它的长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d,或者b<c,a<d(相当于把矩形X旋 ...

  7. DAG模型(矩形嵌套)

    推荐在线例题:http://acm.nyist.net/JudgeOnline/problem.php?pid=16 题摘: 矩形嵌套 时间限制:3000 ms  |  内存限制:65535 KB 难 ...

  8. DAG模型

    数字三角形: 1.递归计算 int solve(int i,int j) { :max(solve(i+,j),solve(i+,j+))); } 2.记忆化搜索,不用指明计算顺序,并且保证每个状态只 ...

  9. DAG 模型 stacking boxes 动态规划

    题目:UVA 103 stacking boxes 题目大意: 给你两个数,一个是盒子的个数,一个是每一个盒子的维数.将一个个盒子互相装起来,让你求最多可以装多少个,要求字典序最小. 解析:这个就是盒 ...

随机推荐

  1. 关于int **

    例子1: int foo(int *array) { array = (); ; } //外头调用 int * uidArray = NULL; foo(uidArray): 这时候我想要在函数里给数 ...

  2. Storm系列(十二)架构分析之Worker-心跳信息处理

    Worker通过worker-data方法定义了一个包含很多共享数据的映射集合,Worker中很多方法都依赖它 mk-worker 功能: 创建对应的计时器.Executor.接收线程接收消息   方 ...

  3. C语言结构

    一个进程在内存中的布局如图所示:        .text段(正文段)——保存程序所执行的程序二进制文件,CPU执行的机器指令部分:一个程序只有一个副本:只读,防止程序由于意外事故而修改自身指令. . ...

  4. 11.编写一个Java程序,计算半径为3.0的圆周长和面积并输出结果。把圆周率π定义为常量,半径定义为变量,然后进行计算并输出结果。

    package com.hanqi.yzljs; public class yzljs { public static void main(String[] args) {     final dou ...

  5. 一段经典的node.js 数据库高并发实现

    var proxy = new EventProxy();var status = "ready";var select = function(callback){ proxy.o ...

  6. 牛一网ecshop家电数码模板(仿易迅网)for ecshop 2.7.3

            本模板尤其适用于家电数码行业. 本模板已经开发.测试完毕,并开放演示. 本模板支持全站静态.销售数量后台自定义.首页商品独立图片.品牌独立展示.商品精美团购.宽屏窄屏自动识别并切换.分 ...

  7. Android ListView分页加载时图片显示问题

    场景:Android ListView需要分页加载,每个item中会有图片,图片又是从网络下载的. 问题:在滑动加载下一页时,上一页的图片明明已经下载完成了,但是无法显示出来. Bug重现: 1,加载 ...

  8. 机器学习算法-K-means聚类

    引文: k均值算法是一种聚类算法.所谓聚类.他是一种无监督学习,将类似的对象归到同一个蔟中.蔟内的对象越类似,聚类的效果越好. 聚类和分类最大的不同在于.分类的目标事先已知.而聚类则不一样. 由于其产 ...

  9. iostat详解

    http://www.penglixun.com/tech/system/use_iostat_analyse_linux_disks.html

  10. LoC

    对于图片.Flash等非文本文件统计文件数量.文件大小: 对于文本文件统计文件数量.文本行数.字符数: