动态规划求解带权有向图最短路径问题

求带权有向图的最短路径问题,最通用也是最容易想到的就是用Dijkstra算法求解,但是有一部分特定的带权有向图最短路径问题也可以用动态规划求解。

这道题看到第一眼很明显就可以生成一张图,然后用带权图的最短路径搜索来做,即Dijkstra算法,但是实际上也可以用动态规划来做,而且这种题还是非常典型的动态规划题目。

得出一个动态规划算法的要点就是想出状态转移方程,这道题的状态转移方程非常明显,建立一个二维数组,行数为i,列数为j

那么dp[i][j]=min(dp[i-1][j],dp[i][j-1])+m[i][j],用中文写大概就是 

从初始点出发到第i行第j列的最短路径为=两条路线的小值(路径1:初始点到该点左边的路径,路径2:初始点到该点上方的路径)+该点的权值

在例题数据中随便取一点3,可以看出依赖于左方的1和上方的5。

那么接下来根据数学归纳法只要先列出基本情况,然后按照依赖方向递推计算,最后就可以得到初始点1到该矩阵任意一点的最短路径,当然也包括到终点0的最短路径

基本情况就是顶点没有左顶点或者没有上顶点,那么就是第一行和第一列,将他们填充为初始值即可。

剩下的所有值都可以根据该依赖来计算,根据依赖方向,按行来算和按列来算都可以,只要保证计算一个值的依赖值都被计算过即可。


比较一下这个算法和Dijkstra算法,可以看到该算法其实求解了多余的节点,许多在最短路径中没有出现过的节点也被计算到了,如果用Dijkstra算法的话,很可能会少计算一些节点。不过只要将该动态规划变成带记忆的从顶向下算法,就可以避免这个问题。

虽然只是求最短路径的话,两种算法都可以

再看另外一个题,这道题就没法用Dijkstra算法来求了

这是一个codewar上的题

https://www.codewars.com/kata/551f23362ff852e2ab000037/java

题目简单意思就是求最长路径

Dijkstra算法是求不出最长路径的,而且任何的贪婪算法都求不出最长路径,所以此时时间复杂度最低的办法还是用动态规划。

解法如下

    public static int longestSlideDown(int[][] pyramid) {

        int[][] temp = new int[pyramid.length][];
        //为了不改变原始数据先复制一份
        for (int y = 0; y < pyramid.length; y++) {
            temp[y] = new int[pyramid[y].length];
            for (int x = 0; x < pyramid[y].length; x++) {
                temp[y][x] = pyramid[y][x];
            }
        }

        //按照依赖方向从上到下计算
        for (int y = 0; y < pyramid.length - 1; y++) {
            for (int x = 0; x < pyramid[y].length; x++) {
                //状态转移方程
                temp[y + 1][x] = Math.max(temp[y + 1][x], temp[y][x] + pyramid[y + 1][x]);
                temp[y + 1][x + 1] = Math.max(temp[y + 1][x + 1], temp[y][x] + pyramid[y + 1][x + 1]);
            }
        }
    
        return Arrays.stream(temp[temp.length - 1]).max().getAsInt();
    }

 

 


这种题型也是常见的动态规划考题,但是我们也可以从中归纳出一些东西,最后总结如下

只要一个有向图没有环,(就是他实际上是一棵树)则该图中任意两点间的最短路径就可以用以上动态规划方法来进行求解,只要搞清楚以下依赖,即从初始点到x点的最短路径等于所有进入x点的顶点的最短路径,再加上对应边的权,取其中最小值。基本情况就是没有入边的顶点。

如下是某个不带环的图的一部分,ABC是所有进入D的顶点,那么图中任意一点到D点的最短路径必然经过ABC中的一点,所以图中任意一点到D的最短路径就是任意一点到A或者B或者C的最短路径再加上ABC到D对应边的权,然后取其中最小值。

那么为什么有环就不能用常规的动态规划方法求解呢,因为会出现循环依赖,这样的话就没法进行递推计算了。不过也可以用一些方法预处理掉环再用动态规划,不过一般出现这样的情况,还是直接用一些启发式的最短路径算法时间复杂度更低

 

 

 

 

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值