转载:动态规划以及路径记录

转自:http://www.cnblogs.com/stemon/p/4635256.html

题目:给定一个矩阵,从左上角开始每次只能向右或者向下移动,最后到达右下角的位置,路径上的所有的数字累加起来作为这条路径的路劲和。要求返回所有路径和中的最小路径和。

举例:

路径1,3,1,0,6,1,0是所有路径中路径和最小的,所以返回其和12。

解析:

这个题目很类似之前的那个动态规划的数字三角的问题。毫无疑问的,这个问题也是用动态规划解决。只要确定了状态和转移方程,这个题目很容易解决。下面直接给出代码:

//利用path记录路径,对于每一个path[i][j],0代表dp[i][j]的值从上面加过来,1代表dp[i][j]的值从左边加过来
int minPathSum1(int matrix[][col], int dp[][col], int path[][col])
{
    if(matrix == NULL)
    {
        return 0;
    }

    dp[0][0] = matrix[0][0];

    //计算第一列的值
    for(int i = 1; i < row; i ++)
    {
        dp[i][0] = dp[i - 1][0] + matrix[i][0];

        path[i][0] = 0;
    }

    //计算第一行的值
    for(int j = 1; j < col; j++)
    {
        dp[0][j] = dp[0][j- 1] + matrix[0][j];

        path[0][j] = 1;
    }

    //计算其它的值
    for(int i = 1; i < row; i++)
    {
        for(int j = 1; j < col; j++)
        {
            int direction = dp[i][j-1] < dp[i-1][j] ? 1 : 0;
            dp[i][j] = (direction ?  dp[i][j-1] : dp[i-1][j]) + matrix[i][j];
            path[i][j] = direction;
        }
    }//for

    return dp[row - 1][col - 1];
}

这里在dp上存储每个点的最短路径和,在path上存储这个最短路径是哪个点过来的。这样就能在找到最短路径和的同时,把路径一块找到。

二维动态规划的空间压缩

上面的题目很简单,不是这篇文章的重点,下面来看一下二维动态规划的空间压缩问题。上面的动态规划的时间复杂度是O(M*N),空间复杂度就是二维数组的大小O(M*N)。空间压缩的方法是不用记录所有的子问题的解。所以就可以只用一个行数组记录第一行、第二行...一次计算。直到最后一行,得到dp[N-1]就是左上角到右下角的最小路径和。

代码实现:

int minPathSum2(int matrix[][col], int dp[])
{
    dp[0] = matrix[0][0];
    //计算第一行的最短路径
    for(int j = 1; j < col; j++)
    {
        dp[j] = dp[j-1] + matrix[0][j];
    }

    //计算除了第一行的其它最小路径和
    for(int i = 1; i < row; i++)
    {
        for(int j = 0; j < col; j++)
        {
            if(j == 0)
            {
                dp[j] += matrix[i][j];
            }
            else
            {
                dp[j] = dp[j-1] < dp[j] ? dp[j-1] : dp[j];
                dp[j] += matrix[i][j];
            }
        }//for
    }//for

    return dp[col - 1];
}

这种二维动态规划的空间压缩几乎可以应用到所有的二维动态规划的题目中,通过一个数组(列数组或者航数组)滚动更新的方式节省了大量的空间。但是在滚动的过程中动态规划表不断的被行数组或者列数组覆盖更新,最后得到的仅仅是动态规划表的最后一行或者最后一列的最小路径和。所以真正的最小路径是不能通过动态规划表回溯得到的。

原文地址:https://www.cnblogs.com/rainsoul/p/8205618.html

时间: 2024-07-30 19:41:25

转载:动态规划以及路径记录的相关文章

HDU1385 Minimum Transport Cost 【Floyd】+【路径记录】

Minimum Transport Cost Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7496    Accepted Submission(s): 1918 Problem Description These are N cities in Spring country. Between each pair of cities

hdu 1258 Sum It Up (dfs+路径记录)

Sum It Up Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3953    Accepted Submission(s): 2032 Problem Description Given a specified total t and a list of n integers, find all distinct sums usi

Charlie&#39;s Change_完全背包&amp;&amp;路径记录

Description Charlie is a driver of Advanced Cargo Movement, Ltd. Charlie drives a lot and so he often buys coffee at coffee vending machines at motorests. Charlie hates change. That is basically the setup of your next task. Your program will be given

POJ1734 Sightseeing trip 【Floyd】+【最小环】+【路径记录】

Sightseeing trip Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4830   Accepted: 1857   Special Judge Description There is a travel agency in Adelton town on Zanzibar island. It has decided to offer its clients, besides many other attra

HDU 1104 Remainder(BFS路径记录+数论)

Remainder Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4337    Accepted Submission(s): 1095 Problem Description Coco is a clever boy, who is good at mathematics. However, he is puzzled by a d

HDU - 1160 FatMouse&#39;s Speed(dp+路径记录)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1160 题意:给定x组老鼠的重量(W)和速度(S).求使得   W[m[1]] < W[m[2]] < ... < W[m[n]]       S[m[1]] > S[m[2]] > ... > S[m[n]] 的最长序列长度和路径 题解:排序一下,然后LIS,路径记录一下,输出就可以了 1 #include <iostream> 2 #include <a

台州 OJ 2537 Charlie&#39;s Change 多重背包 二进制优化 路径记录

描述 Charlie is a driver of Advanced Cargo Movement, Ltd. Charlie drives a lot and so he often buys coffee at coffee vending machines at motorests. Charlie hates change. That is basically the setup of your next task. Your program will be given numbers

[bfs+余数判重+路径记录] hdu 4474 Yet Another Multiple Problem

题意: 给一个n和m个数字(一位数) 求最小的n的倍数不含有这m个数字,不存在输出-1 思路: 首先有可能这个数超long long 所以无法暴力解决 所以这题应该是一个bfs 为什么能用余数判重呢 对于当前的余数进到队列里,一定是这个余数对应数的最小值 接下来再怎么添加到满足条件的后续东西应该是一样的 所以就可以余数判重了,类似数位dp的记录方式 然后再加上一个路径记录就好了 代码: #include"cstdlib" #include"cstdio" #incl

迷宫bfs+路径记录

给定5*5的地图,1表示墙,0表示空地,从左上角走到左下角 是把所有的可走路径都记录下来了,但是 搜索有递归与非递归形式 本代码使用非递归形式 bfs+路径记录 对于num[i].pre=head的理解是他存在很多条路,每个点是从上一个点走过来的,但总存在一条路是到达终点的,所以,只需要得到到终点的一个head就可以顺着这个路径标记回去了 #include <iostream> #include <cstdio> using namespace std; char a[10][10