动态规划实例(六):最小花费路径

来源:互联网 发布:男人中式服装品牌知乎 编辑:程序博客网 时间:2024/05/19 05:32
    给定一个矩阵cost[][]和其中的一个位置(m,n),写一个函数,返回从到达(0,0)到(M,N)最小成本路径的花费。该矩阵的每个格子代表遍历该格子的花费。到达(M,N)的路径的总成本是该路径上(包括源和目标)所有的费用总和。你只能从开始位置 向右、下和右下走,也就是说,从一个给定的格子(I,J),只有(i+1,j)的(i,j +1)和
(i +1, j +1)的可以通过。你可以假设所有的花费都是正整数。
    例如,在下面的图中,到(2,2)的最小花费路径?
         1 2 3
         4 8 2
         1 5 3
     最小花费的路径,如下图高亮显示。 的路径为(0,0) – >(0,1) – >(1,2) – >(2,2)。 路径的成本是8 (1 + 2 + 2 + 3)
     1)最优子结构 
        到达(M,N)必须通过3格子中的一个:(M-1,N-1)或(m-1,n)或(M,N-1)。 到达(M,N),所以最小的花费路径可以写成“3个格子最小的 加[M] [N]的花费”。
        minCost(m, n) = min (minCost(m-1, n-1), minCost(m-1, n), minCost(m, n-1)) + cost[m][n]
     2)重叠子问题 

具体实例及代码如下所示:

/** * @Title: MinCost.java * @Package dynamicprogramming * @Description: TODO * @author peidong * @date 2017-6-6 上午10:06:24 * @version V1.0 */package dynamicprogramming;/** * @ClassName: MinCost * @Description: 最小花费路径 * @date 2017-6-6 上午10:06:24 * */public class MinCost {    /**     *     * @Title: minCostRecursion     * @Description: 利用递归求解最小花费路径     * @param cost     * @param m     * @param n     * @return     * @return int     * @throws     */    public static int minCostRecursion(int[][] cost, int m, int n){        //边界条件判断        if( n <0 || m < 0){            return -1;        }else if(m ==0 && n ==0){            return cost[m][n];        }else{            return cost[m][n] + min(minCostRecursion(cost, m-1, n), minCostRecursion(cost, m, n-1), minCostRecursion(cost, m-1, n-1));        }    }    /**     *     * @Title: min     * @Description:返回最小值     * @param a     * @param b     * @param c     * @return     * @return int     * @throws     */    public static int min(int a, int b, int c){        return Math.min(Math.min(a,b), c);    }    public static int minCost(int[][] cost, int m, int n){        //创建转移矩阵(花费累加矩阵)        int[][] tc = new int[m+1][n+1];        tc[0][0] = cost[0][0];        //初始化转移矩阵        for(int i = 1; i <= m; i++){            tc[i][0] = tc[i-1][0] + cost[i][0];        }        for(int j = 1; j <= n; j++){            tc[0][j] = tc[0][j-1] + cost[0][j];        }        //状态转移矩阵        for(int i = 1; i <= m; i++){            for(int j =1 ; j <= n; j++){                tc[i][j] = min(tc[i-1][j-1], tc[i-1][j], tc[i][j-1]) + cost[i][j];            }        }        //打印状态转移矩阵        for(int i = 0; i <= m; i++){            for(int j = 0; j <= n; j++){                System.out.print(tc[i][j] + " ");            }            System.out.println();        }        return tc[m][n];    }    /**     * @Title: main     * @Description: TODO     * @param args     * @return void     * @throws     */    public static void main(String[] args) {        // TODO Auto-generated method stub        int[][] cost ={                {1, 2, 3},                {4, 8, 2},                {1, 5, 3}};        System.out.println("使用递归获取最小花费为:" + minCostRecursion(cost, 2, 2));        System.out.println("使用动态规划获取最小花费为:" + minCost(cost, 2, 2));    }}