leetcode 64. Minimum Path Sum
一、问题描述
给定一个填充非负数的m×n网格,找到一条从左上角到右下角的路径,该路径使沿路径上的所有数字的总和最小。
注意:您只能在任何时间点向下或向右移动。
【举例】
输入:[
[1,3,1]
[1,5,1]
[4,2,1]
]
输出:7
说明:因为路径1-3-1-1-1使总和最小化。
本题解法思想与笔者之前写过的一篇方法如出一辙,可参考学习: 三角数字自上而下求最值和【dfs+动规】
二、解题算法
方法1 -- 常规DFS--会超时
/************************************************************** leetcode 64. Minimum Path Sum Author:tmw date:2018-5-26 **************************************************************/ #include <stdio.h> #include <stdlib.h> /** 方法一:常规dfs -- 会超时 终止条件(数据非法):i>=rowSize||j>=colSize 收敛条件(获得一种可行解):i==rowSize&&j==colSize --- grid[i][j] 剪枝条件--这里同终止条件 递归方向: 向下:dfs(grid,colSize,rowSize,i++,j) 向右:dfs(grid,colSize,rowSize,i,j++) **/ #include <limits.h> #define min(a,b) ( a<b?a:b ) int dfs(int** grid, int rowSize, int colSize, int i, int j) { //终止条件 if( i>=rowSize || j>=colSize ) return INT_MAX; //收敛条件 if( i==rowSize-1 && j==colSize-1 ) return grid[i][j]; //递归方向 return min(dfs(grid,rowSize,colSize,i+1,j),dfs(grid,rowSize,colSize,i,j+1))+grid[i][j]; } int minPathSum(int** grid, int gridRowSize, int gridColSize) { return dfs(grid,gridRowSize,gridColSize,0,0); }
方法2 -- 加备忘录DFS--accept
/** 方法二:加备忘录的dfs 递归方式与上一样 加一个二维数组用来存储中间结果,表示走到当前的[i][j]位置的min path **/ #define min(a,b) ( a<b?a:b ) #include <limits.h> int dfs_MEM( int** grid, int rowSize, int colSize, int i, int j, int** record ) { //终止条件 if( i>=rowSize || j>=colSize ) return INT_MAX; if(record[i][j]>0) return record[i][j]; //收敛条件 if( i==rowSize-1 && j==colSize-1 ) return grid[i][j]; record[i][j]=min(dfs_MEM(grid,rowSize,colSize,i+1,j,record),dfs_MEM(grid,rowSize,colSize,i,j+1,record))+grid[i][j]; return record[i][j]; } int minPathSum(int** grid, int gridRowSize, int gridColSize) { /**为结果数组申请空间并赋值**/ int** record = (int**)malloc(gridRowSize*sizeof(int*)); int i,j; for(i=0; i<gridRowSize; i++) record[i] = (int*)malloc(gridColSize*sizeof(int)); for(i=0; i<gridRowSize; i++) for(j=0; j<gridColSize; j++) record[i][j] = 0; return dfs_MEM(grid,gridRowSize,gridColSize,0,0,record); }
方法3 -- 动态规划--accept
/** 方法三:动态规划 采用动态规划思想,要求到达[gridRowSize-1][gridColSize-1]的最小开销路径, 则: 1)要么是从到[gridRowSize-1][gridColSize-2]的最小开销+grid[gridRowSize-1][gridColSize-1] 2)要么是从到[gridRowSize-2][gridColSize-1]的最小开销+grid[gridRowSize-1][gridColSize-1] 所以,递归表达式为:f[i][j] = min(f[i-1][j],f[i][j-1])+a[i][j] **/ #define min(a,b) (a<b?a:b) int minPathSum(int** grid, int gridRowSize, int gridColSize) { //申请f空间 int i,j; int** f=(int**)malloc(gridRowSize*sizeof(int*)); for(i=0;i<gridRowSize;i++) f[i]=(int*)malloc(gridColSize*sizeof(int)); //初始化f的边界--- f[i][j]为到达点[i][j]所经过的最小开销 f[0][0] = grid[0][0]; for(i=1; i<gridRowSize; i++) f[i][0] = f[i-1][0] + grid[i][0]; for(j=1; j<gridColSize; j++) f[0][j] = f[0][j-1] + grid[0][j]; //填满f[][]数组 for(i=1; i<gridRowSize; i++) for(j=1; j<gridColSize; j++) f[i][j] = min(f[i-1][j],f[i][j-1])+grid[i][j]; return f[gridRowSize-1][gridColSize-1]; }
梦想还是要有的,万一实现了呢~~~~ヾ(◍°∇°◍)ノ゙~~~