现有一个地图,由横线与竖线组成(参考围棋棋盘),且两点之间有行走距离起点为左上角,终点为右下角在地图上,每次行走只能沿线移动到临近的点,并累加路径计算一个人从地图的起点走到终点的最小路径为多少。
m*n地图表示如下:
3
3
1 3 4
2 1 2
4 3 1
其中m=3,n=3 表示3*3的矩阵
行走路径为:下>右>右>下
路径总长:1+2+1+2+1=7
1 2 1 2
3
2 3 9 8 6 2 3 7
21
地图参数为:
1
2
1 2
m=1,n=2,表示1*2的矩阵,最短距离是左>右
import java.util.Scanner;
public class Main {
// 分析: 从左往右的尝试
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int row = in.nextInt();
int col = in.nextInt();
int[][] array = new int[row][col];
in.nextLine();
for (int i = 0; i < row; i++) {
String[] numbers = in.nextLine().split(" ");
for (int j = 0; j < col; j++) {
array[i][j] = Integer.parseInt(numbers[j]);
}
}
System.out.println(process1(array, row, col, 0, 0));
System.out.println(process2(array));
System.out.println(process3(array));
}
// 暴力递归. 返回值表示从当前位置出发,到结束时,最小的路径.
private static int process1(int[][] array, int row, int col, int i, int j) {
if (i == row - 1 && j == col - 1) { // 终止位置
return array[i][j];
}
if (i == row - 1) { // 最后一行,非终止位置
return array[i][j] + process1(array, row, col, i, j + 1);
}
if (j == col - 1) { // 最后一列,非终止位置
return array[i][j] + process1(array, row, col, i + 1, j);
}
// 中间,取朝右或者朝下中较小值,在加上当前值
return Math.min(process1(array, row, col, i, j + 1), process1(array, row, col, i + 1, j)) + array[i][j];
}
// 记忆化搜索,动态规划
private static int process2(int[][] array) {
int row = array.length;
int col = array[0].length;
int[][] dp = new int[row][col];
dp[row - 1][col - 1] = array[row - 1][col - 1];
for (int j = col - 2; j >= 0; j--) {
dp[row - 1][j] = array[row - 1][j] + dp[row - 1][j + 1];
}
for (int i = row - 2; i >= 0; i--) {
dp[i][col - 1] = array[i][col - 1] + dp[i + 1][col - 1];
}
for (int i = row - 2; i >= 0; i--) {
for (int j = col - 2; j >= 0; j--) {
dp[i][j] = Math.min(dp[i][j + 1], dp[i + 1][j]) + array[i][j];
}
}
return dp[0][0];
}
// 直接修改原数组,从右往左,由下到上推结果. 动态规划
private static int process3(int[][] array) {
int row = array.length;
int col = array[0].length;
for (int j = col - 2; j >= 0; j--) {
array[row - 1][j] += array[row - 1][j + 1];
}
for (int i = row - 2; i >= 0; i--) {
array[i][col - 1] += array[i + 1][col - 1];
}
for (int i = row - 2; i >= 0; i--) {
for (int j = col - 2; j >= 0; j--) {
array[i][j] += Math.min(array[i][j + 1], array[i + 1][j]);
}
}
return array[0][0];
}
}