算法思想之动态规划(二)——最小路径和问题

前言

我们在算法思想之动态规划(一)中讨论了动态规划的基本概念、性质和引入,如果你还没有看的话建议先去看一下。今天我们讨论一下经典的动态规划问题之最小路径和问题

最小路径和问题

问题描述

有一个矩阵map,它每个格子有一个权值。从左上角的格子开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,返回所有的路径中最小的路径和。

问题分析

假设,一个矩阵map的行数和列数,且矩阵中从左上角出发到达第行,第列的最小路径为,则:

  • 对于, 很显然,

  • 对于第一行元素,即来说,最小路径为从矩阵左上角出发到达前一位置(第0行,第列)的最小路径 + 当前位置的权值。即,

  • 同理,对于第一列元素,即来说,最小路径为从矩阵左上角出发到达前一位置(第0列,第行)的最小路径 + 当前位置的权值。即,

  • 对于其他元素,即来说,最小路径为从矩阵左上角出发到达前2个位置(, )以及(, )中的较小值 + 当前位置的权值。即

我们要求的是。

代码实现

我们对该问题使用暴力搜索、记忆搜索和动态规划三种方法进行实现。

public class MinimumPath {
    public static HashMap hashMap;

    public int getMin(int[][] map, int n, int m) {
        if (n == 0 || m == 0) {
            return 0;
        }
//        return core1(map, n, m);
//        return core2(map, n, m);
        return core3(map, n, m);
    }

    /**
     * 暴力搜素
     *
     * @param map
     * @param n
     * @param m
     * @return
     */
    public static int core1(int[][] map, int n, int m) {
        if (n == 1 && m == 1) {
            return map[n - 1][m - 1];
        }

        int res = map[n - 1][m - 1];
        if (n == 1 && m > 1) {
            res += core1(map, n, m - 1);
        } else if (n > 1 && m == 1) {
            res += core1(map, n - 1, m);
        } else if (n > 1 && m > 1) {
            res += Math.min(core1(map, n, m - 1), core1(map, n - 1, m));
        }
        return res;
    }


    /**
     * 记忆搜索
     *
     * @param map
     * @param n
     * @param m
     * @return
     */
    public static int core2(int[][] map, int n, int m) {
        if (hashMap == null) {
            hashMap = new HashMap<>();
        }

        String key = String.valueOf(n) + "_" + String.valueOf(m);
        if (n == 1 && m == 1) {
            hashMap.put(key, map[n - 1][m - 1]);
            return map[n - 1][m - 1];
        }
        if (hashMap.containsKey(key)) {
            return hashMap.get(key);
        }
        int res = map[n - 1][m - 1];
        if (n == 1 && m > 1) {
            res += core2(map, n, m - 1);
        } else if (n > 1 && m == 1) {
            res += core2(map, n - 1, m);
        } else if (n > 1 && m > 1) {
            res += Math.min(core2(map, n, m - 1), core2(map, n - 1, m));
        }
        hashMap.put(key, res);
        return res;
    }

    /**
     * 动态规划
     *
     * @param map
     * @param n
     * @param m
     * @return
     */
    public static int core3(int[][] map, int n, int m) {
        int[][] dp = new int[n][m];
        dp[0][0] = map[0][0];
        for (int i = 1; i < m; i++) {
            dp[0][i] = dp[0][i - 1] + map[0][i];
        }
        for (int i = 1; i < n; i++) {
            dp[i][0] = dp[i - 1][0] + map[i][0];
        }
        for (int i = 1; i < n; i++) {
            for (int j = 1; j < m; j++) {
                dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + map[i][j];
            }
        }
        return dp[n - 1][m - 1];
    }

    public static void main(String[] args) {
        MinimumPath minimumPath = new MinimumPath();
        int[][] map = new int[5][4];
        map[0] = new int[]{533,385,398,226};
        map[1] = new int[]{59,529,215,203};
        map[2] = new int[]{466,262,210,597};
        map[3] = new int[]{32,359,616,194};
        map[4] = new int[]{322,485,552,493};
        int res = minimumPath.getMin(map, map.length, map[0].length);
        System.out.println(res);
    }
}

其他经典问题

  • 算法思想之动态规划(三)——找零钱问题
  • 算法思想之动态规划(四)——最长公共子序列问题
  • 算法思想之动态规划(五)——最小编辑距离问题
  • 算法思想之动态规划(六)——最长上升子序列问题
  • 算法思想之动态规划(七)——背包问题

未来几篇博文,我将继续对经典的动态规划问题进行整理,敬请关注~
由于本人水平有限,文章难免有欠妥之处,欢迎大家多多批评指正!

写在最后

欢迎大家关注我的个人博客复旦猿。

你可能感兴趣的:(算法思想之动态规划(二)——最小路径和问题)