夕拾算法进阶篇:32)DAG最长路(动态规划DP)
来源:互联网 发布:linux 查看mysql.pid 编辑:程序博客网 时间:2024/05/16 07:03
之前介绍了DAG有向无环图以及拓扑排序,如何求解DAG的最长路,也就是所谓的“”关键路径”,但求解关键的路径的做法对初学者来说实在不易。因此下面介绍一种简便的方法,来求解DAG最长路(最短路的思想是一致的)。
下面着重解决两个问题:
(1)求整个DAG的最长路径(即不固定起点和终点)
(2)固定终点,求DAG的最长路径
首先讨论第一个问题:给定一个有向无环图,怎样求解整个图的所有路径中权值之和最大的那条。针对这个问题令dp[i]表示从i顶点出发能获得的最长路径长度,这样所有的d[i]的最大值就是整个DAG的最长路径长度。
那怎么求解dp数组呢?注意到dp[i]表示从i顶点出发能获得的最长路径长度,如果从i号顶点出发能直接到达顶点j1,j2..jk,而dp[j1]..dp[jk]均已知。那么就有
dp[i]=max{dp[j]+length[i->j](i,j)∈E}
显然,根据上面的思路需要按照逆拓扑排序来求解dp数组(因为最后的顶点没有出边),但有木有办法不求逆拓扑排序也能计算dp数组呢?当然有,那就是递归。其基于邻接矩阵实现的代码如下:
int DP(int i){if(dp[i]>0) return dp[i];for(int j=0;j<n;j++){ //遍历i的所有可达出边 if(map[i][j]!=Inf){dp[i]=max(dp[i],DP(j)+map[i][j]); } }return dp[i]; }由于从出度为0的顶点出发的最长路径长度为0,因此边界就是这些点,但在具体实现中不妨对整个dp数组初始化为0。这样DP函数当前访问顶点i的出度为0时就会直接返回dp[i]=0(以此为边界),而出度不为0的时候就会递归求解,递归过程中遇到已经计算过的顶点则直接返回对于的dp值,于是从逻辑上实现了逆拓扑排序的效果。
那如果记录这条路径呢?回忆下求使用Dikskstra求解最短路径的在优化顶点v时候,使用了一个pre数组来保存v的前驱结点u。事实上,可以把这种想法应用于求解最长路径上,使用一个next数组保存i顶点的后继顶点,此时只需要顺序地打印路径即可。
int DP(int i){if(dp[i]>0) return dp[i];for(int j=0;j<n;j++){ //遍历i的所有可达出边 if(map[i][j]!=Inf){int temp=DP(j)+map[i][j];//单独计算dp if(dp[i]<temp){//可以获得更长的路径 dp[i]=temp; next[i]=j; //保存i的后继顶点j }} }return dp[i]; }//调用前需先获得最大的dp[i],然后将i作为路径的起点传入 void printPath(int i){cout<<i;while(next[i]!=-1){//next数组初始化为-1 i=next[i]; cout<<"->"<<i; } }
接下来再看看问题(2):固定终点,求DAG的最长路径,有了上面的经验,应当能很容易想到这个问题延伸问题的解决方案。假设规定的终点为T。那么可以令dp[i]表示从i号顶点出发到达终点T能获得的最长路径长度。,如果从i号顶点出发能直接到达顶点j1,j2..jk,而dp[j1]..dp[jk]均已知,那么就有dp[i]=max{dp[j]+length[i->j](i,j)∈E} 。可以发现怎么和问题(1)的式子是一样的。如果仅仅是这样就无法体现出dp数组的含义中添加的“到达终点T的描述”。
那么这两个问题的区别在哪呢?没错,边界。在第一个问题中没有固定的终点,因此所有出度为0的顶点dp值为0是边界;但在这个问题中固定了终点,因此边界应当为dp[T]=0。那么还能像之前那样对整个dp数组初始化为0?不行,此处会有个问题,由于从某顶点出发可能无法到达终点T(例如出度为0的顶点),因此按照之前的做法出度为0的顶点到T的最长路径长度为0,这显然是不符合逻辑的。合适的做法是初始化dp数组为一个负的大数,来保证“”无法到达终点”的含义得以表达(即-Inf,消除其他出度为0的顶点对前驱结点的最长距离的干扰);然后设置一个vis数组表示顶点是否已经被计算(问题1不用设置是因为dp的初始值为0,而问题2的dp初始值为-Inf), 代码如下:
int DP(int i){if(vis[i]) return dp[i]; //dp[i]已经计算得到vis[i]=true;for(int j=0;j<n;j++){ //遍历i的所有可达出边 if(map[i][j]!=Inf){dp[i]=max(dp[i],DP(j)+map[i][j]);} }return dp[i]; }
最后看一个经典的矩阵嵌套问题
题目描述
有n个矩形,每个矩形可以用a,b来描述,表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。
输入
第一行是一个正正数N(0<N<10),表示测试数据组数,
每组测试数据的第一行是一个正正数n,表示该组测试数据中含有矩形的个数(n<=1000)
随后的n行,每行有两个数a,b(0<a,b<100),表示矩形的长和宽
输出
每组测试数据都输出一个数,表示最多符合条件的矩形数目,每组输出占一行
样例输入
1
10
1 2
2 4
5 8
6 10
7 9
3 1
5 8
12 10
9 7
2 2
样例输出
5
分析:将每个矩阵都视为一个顶点,并将嵌套关系视为顶点和顶点之间的有向边,边权皆为1,于是就转换成了DAG最长路问题了。
#include <iostream>#include <algorithm>#include <cstring>using namespace std;const int M=1002;int map[M][M],dp[M],n;struct Rec{int x,y;}rec[M]; int DP(int i){if(dp[i]>0) return dp[i];for(int j=0;j<n;j++){ //遍历i的所有可达出边 if(map[i][j]){dp[i]=max(dp[i],DP(j)+map[i][j]); } }return dp[i]; }//检查a<c,b<d或者b<c,a<dint check(Rec r1,Rec r2){if(r1.x<r2.x&&r1.y<r2.y){return 1;}if(r1.x<r2.y&&r1.y<r2.x){return 1;}return 0; } int main(){int i,m,j;cin>>m;while(m--){memset(dp,0,sizeof(dp));memset(map,0,sizeof(map)); cin>>n;for(i=0;i<n;i++){cin>>rec[i].x>>rec[i].y;}for(i=0;i<n;i++){for(j=0;j<n;j++){if(i!=j) //设置边的关系,0为无边 map[i][j]=check(rec[i],rec[j]);}}DP(0);int max_=-1;for(i=0;i<n;i++){if(max_<dp[i])max_=dp[i];}cout<<max_+1<<endl; //顶点数为边数 }}
- 夕拾算法进阶篇:32)DAG最长路(动态规划DP)
- 夕拾算法进阶篇:14)最长上升子序列(动态规划DP)
- 夕拾算法进阶篇:15)最长公共子序列(动态规划DP)
- 夕拾算法进阶篇:16)最长回文子串(动态规划DP)
- 夕拾算法进阶篇:12)出栈序列统计(动态规划DP)
- 夕拾算法进阶篇:13)最大连续子序列(动态规划DP)
- 夕拾算法进阶篇:17)01背包和完全背包问题 (动态规划DP)
- 夕拾算法进阶篇:18)装箱问题 (01背包_动态规划DP)
- 夕拾算法进阶篇:19)采药 (01背包_动态规划DP)
- 夕拾算法进阶篇:20)货币系统 (完全背包_动态规划DP)
- 夕拾算法进阶篇:28)矩阵连乘(动态规划DP)
- NYOJ - 16 - 矩形嵌套(DAG最长路,动态规划)
- 夕拾算法进阶篇:21)最长公共子串(DP+后缀数组)
- UVA103动态规划之DAG上的最长路及其字典序
- 动态规划(DP)算法
- DP动态规划算法
- 算法进阶之动态规划
- 动态规划进阶篇
- SQL基础语句
- web开发
- java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start com
- 02_Java面向对象
- OpenGL Android平台图片组件设计
- 夕拾算法进阶篇:32)DAG最长路(动态规划DP)
- ADO接口简介
- Sport Book 0.3% Rebate Bonus Promotion in Newcity8 Online Casino Malaysia
- WebView的使用
- echarts如何给柱形图的每个柱子设置不同颜色
- 读懂diff
- 系统时间自动加上相应的小时
- 为什么我会得到“必须先修复所有的编译错误才能进入Play模式!”的错误?
- flatMap与Monad(Swift)