有向无环图上的动态规划是学习动态规划的基础,很多问题都可以转化为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. SPI协议及其工作原理浅析

    转载自:http://bbs.chinaunix.net/thread-1916003-1-1.html一.概述. SPI, Serial Perripheral Interface, 串行外围设备接 ...

  2. globalfifo设备驱动

    把globalmem中的全局内存变成一个FIFO,只有当FIFO中有数据的时候(即有进程把数据写到这个FIFO而且没有被读进程读空),读进程才能把数据读出,而且读取后的数据会从globalmem的全局 ...

  3. HDOJ-ACM1014(JAVA)

    这道题题意: 求最大公约数,最大公约数是1,则GOOD,否则BAD 注意: 输出时,如果是System.out.printf("%10d%10d    Good Choice\n\n&quo ...

  4. 委托demo

    delegate bool Filter(string s); class test { static void Main() { Filter f=new Filter(A); Display(ne ...

  5. NULL指针 Void* 和野指针

    在C和C++的语言中常常有这几个概念: NULL指针.空指针.Void *指针.野指针(Wild Pointer)甚至垂悬指针(Dangling Pointer). 1.NULL指针,一般用于指向一个 ...

  6. openstack 正常流量

  7. http://www.cnblogs.com/xdp-gacl/p/3622275.html

    http://www.cnblogs.com/xdp-gacl/p/3622275.html

  8. 解决TortoiseCVS中文乱码

    解决TortoiseCVS中文乱码必备,解决方法: 第一:卸载和TortoiseCVS安装一起安装的CVSNT. 第二:安装本版本CVSNT. CVSNT下载地址:http://down.51cto. ...

  9. android 4.3源码编译

    jianguoliao@jianguoliao-Lenovo-IdeaPad-Y470:~/WORKING_DIRECTORY$ source build/envsetup.sh including ...

  10. log4net(c#) 配置及使用

    1. 首先从apache网站下载log4net, http://logging.apache.org/log4net/download_log4net.cgi .我下的是最新版本 log4net-1. ...