题目
给定一个矩阵m, 从左上角开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的树子累加起来就是路径和,返回所有的路径中最小的路径和.
解法一
这是一道经典的动态规划题,状态转移方程为dp[i][j] = min{dp[i - 1][j], dp[i][j - 1]} + m[i][j].可以用一个二维的dp矩阵来求解.对于dp矩阵,第一行和第一列只会有一种走法,就是从左到右或者从上到下的累加,所以可以先进行初始化,然后其他元素就可以用过转移方程一个一个填充,知道把整个dp矩阵填充完毕.
解法二
如果用二维数组,对于m行n列的数组,空间复杂度就是O(m*n).动态规划中常用的优化方法之一就是仅使用一个一维数组在进行这个迭代过程.但是这种空间压缩也有局限性,那就是不能记录获得最后结果的路径.如果需要完整路径的话还是需要二维的动态规划表.
代码
#include <iostream> #include <vector> using namespace std; //使用二维数组的方式 int minPathSum1(int arr[4][4], int m, int n) { if (m == 0 || n == 0) return 0; int dp[m][n]; dp[0][0] = arr[0][0]; for (int i = 1; i < m; i ++) dp[i][0] = dp[i - 1][0] + arr[i][0]; for (int j = 1; j < n; j ++) dp[0][j] = dp[0][j - 1] + arr[0][j]; for (int i = 1; i < m; i ++) { for (int j = 1; j < n; j ++) dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + arr[i][j]; } // print array // for (int i = 0; i < 4; i ++) { // for (int j = 0; j < 4; j ++) // cout<<dp[i][j]<<" "; // cout<<endl; // } return dp[m - 1][n - 1]; } //使用一维数组的方式 int minPathSum2(int arr[4][4], int m, int n) { if (m == 0 || n == 0) return 0; int dp[n]; dp[0] = arr[0][0]; for (int k = 1; k < n; k ++) dp[k] = dp[k - 1] + arr[0][k]; for (int i = 1; i < m; i ++) { for (int j = 0; j < n; j ++) { if (j == 0) dp[j] = dp[j] + arr[i][0]; else { dp[j] = min(dp[j - 1], dp[j]) + arr[i][j]; } } } //print dp array // for (int k = 0; k < n; k ++) // cout<<dp[k]<<" "; // cout<<endl; return dp[n - 1]; } int main() { int arr[4][4] = {{1,3,5,9},{8,1,3,4},{5,0,6,1},{8,8,4,0}}; for (int i = 0; i < 4; i ++) { for (int j = 0; j < 4; j ++) cout<<arr[i][j]<<" "; cout<<endl; } cout<<minPathSum2(arr, 4, 4)<<endl; return 0; }