美文网首页数据结构与算法数据结构与算法思想Java数据结构和算法
算法思想之动态规划(二)——最小路径和问题

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

作者: 复旦猿 | 来源:发表于2019-05-31 14:36 被阅读0次

    前言

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

    最小路径和问题

    问题描述

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

    问题分析

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

    • 对于i=0, j=0, 很显然,
      f(0,0) = map[0][0]

    • 对于第一行元素,即i=0,0<j \leq m-1来说,最小路径为从矩阵左上角出发到达前一位置(第0行,第j-1列)的最小路径 + 当前位置的权值。即,
      f(0, j) = f(0, j-1) + map[0][j]

    • 同理,对于第一列元素,即j=0,0<i \leq n-1来说,最小路径为从矩阵左上角出发到达前一位置(第0列,第i-1行)的最小路径 + 当前位置的权值。即,
      f(i,0) = f(i-1, 0) + map[i][0]

    • 对于其他元素,即1 \leq i \leq n-1,1 \leq j \leq n-1来说,最小路径为从矩阵左上角出发到达前2个位置(i-1, j)以及(i, j-1)中的较小值 + 当前位置的权值。即
      f(i,j) = min(f(i-1,j), f(i, j-1)) + map[i][j]

    我们要求的是f(n-1,m-1)

    代码实现

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

    public class MinimumPath {
        public static HashMap<String, Integer> 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);
        }
    }
    

    其他经典问题

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

    写在最后

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

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/gdqwtctx.html