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];
}
梦想还是要有的,万一实现了呢~~~~ヾ(◍°∇°◍)ノ゙~~~