zoukankan      html  css  js  c++  java
  • 矩阵的最小路径和 动态规划

    * 问题

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

       1 -> 3   5     9

       8    1     3     4

       5    0 -> 6 -> 1

       8    8     4     0

    打印最小路径:

    1->3->1->0->6->1->0

    package cn.mediamix;
    
    import java.util.ArrayList;
    import java.util.LinkedList;
    
    public class MinPath {
    	public static int[][] minPath(int[][] m) {
    		if (m==null||m.length==0||m[0]==null||m[0].length==0) {
    			return null;
    		}
    		int row = m.length, col = m[0].length;
    		int [][]dp = new int[row][col];
    		dp[0][0] = m[0][0];
    	
    		for (int i = 1; i < row; i++) {
    			dp[i][0] = dp[i-1][0] + m[i][0];
    		}
    		for (int j = 1; j < col; j++) {
    			dp[0][j] = dp[0][j-1] + m[0][j];
    		}
    		for (int i = 1; i < row; i++) {
    			for (int j = 1; j < col; j++) {
    				dp[i][j] = Math.min(dp[i-1][j],  dp[i][j-1]) + m[i][j];
    			}
    		}
    	
    		// return dp[row-1][col-1];
    		return dp;
    	}
    	
    	public static String getPath(int [][]dp) {
    		ArrayList<Integer> a = new ArrayList<Integer>(dp.length + dp[0].length - 1);
    		int i = dp.length-1, j = dp[0].length-1;
    		
    		while (0<=i && 0 <= j) {
    			a.add(dp[i][j]);
    			if (0<i && 0<j) {
    				if (dp[i-1][j] < dp[i][j-1]) {i--;}
    				else {j--;}
    			} else if (0 < i) {
    				i--;
    			} else if (0 < j) {
    				j--;
    			} else {
    				break;
    			}
    		}
    		LinkedList<Integer> list = new LinkedList<Integer>();
    		
    		for (i = 0; i < a.size()-1; i++) {
    			list.push(a.get(i)-a.get(i+1));
    		}
    		list.push(a.get(i));
    		
    		StringBuilder sb = new StringBuilder();
    		for(Integer elem:list) {
    			sb.append(elem + "->");
    		}
    		sb.delete(sb.length()-2, sb.length());
    		return sb.toString();
    	}
    	
    	// 空间压缩 不可打印路径
    	public static int minPathSum2(int[][] m) {
    		if (m==null||m.length==0||m[0]==null||m[0].length==0) {
    			return 0;
    		}
    		// 行数与列数较大的那个为more
    		int more = Math.max(m.length,  m[0].length);
    		// 行数与列数较小的那个为less
    		int less = Math.min(m.length, m[0].length);
    		// 行数是不是>=列数
    		boolean rowMore = more == m.length;
    		// 辅助数组的长度仅为行数与列数的最小值
    		int [] arr = new int [less];
    		arr[0] = m[0][0];
    		
    		for (int i = 1; i < less; i++) {
    			arr[i] = arr[i-1]  + (rowMore ? m[0][i] : m[i][0]);
    		}
    		for (int i = 1; i < more; i++) {
    			arr[0] += (rowMore ? m[i][0]:m[0][i]);
    			for (int j = 1; j < less; j++) {
    				arr[j] = Math.min(arr[j-1], arr[j]) +
    						(rowMore ? m[i][j] : m[j][i]);
    			}
    		}
    		
    		return arr[less-1];
    	}
    	
    	public static void main(String[] args) {
    		int [][]m = {
    				{1,3,5,9},
    				{8,1,3,4},
    				{5,0,6,1},
    				{8,8,4,0}
    		};
    		int [][]dp = minPath(m);
    		System.out.println(dp[dp.length-1][dp[0].length-1]);
    		System.out.println(getPath(dp));
    		System.out.println(minPathSum2(m));
    	}
    }
    

      

    Output:

    12

    1->3->1->0->6->1->0

    12

      

    你的独立思考能力正在被它吞噬掉

  • 相关阅读:
    撩课-Web大前端每天5道面试题-Day15
    撩课-Web大前端每天5道面试题-Day14
    撩课-Java每天5道面试题第26天
    撩课-Java每天5道面试题第25天
    撩课-Web大前端每天5道面试题-Day13
    撩课-Java每天5道面试题第24天
    撩课-每天刷Web面试题(前10天汇总)-Day12
    撩课-Java每天5道面试题第23天
    撩课-Web大前端每天5道面试题-Day11
    java设计模式-策略模式
  • 原文地址:https://www.cnblogs.com/mingzhanghui/p/9404642.html
Copyright © 2011-2022 走看看