【动态规划】——数塔(java版,超详图解)

简介: [问题描述]从数塔的顶层出发,在每一个结点可以选择向左走或向右走,直走到最底层,要求找出一条路径,使得路径上的数值和最大。

数塔问题


[问题描述]从数塔的顶层出发,在每一个结点可以选择向左走或向右走,直走到最底层,要求找出一条路径,使得路径上的数值和最大。




问题分析:要求出路径上的数值和最大,只需求出“8"左边(12)和右边(15)的数塔谁最大即可。


左边(12)


要求12这个数塔的路径上的数值和最大,只需求出“12"左边(3)和右边(9)的数塔谁最大

要求3这个数塔的路径上的数值和最大,只需求出“3"左边(8)和右边(10)的数塔谁最大

要求9这个数塔的路径上的数值和最大,只需求出”9"左边(10)和右边(5)的数塔谁最大

........................................................等等等


右边(15)


要求15这个数塔的路径上的数值和最大,只需求出“15"左边(9)和右边(6)的数塔谁最大

要求9这个数塔的路径上的数值和最大,只需求出“9"左边(10)和右边(5)的数塔谁最大

要求6这个数塔的路径上的数值和最大,只需求出”6"左边(5)和右边(12)的数塔谁最大

........................................................等等等


可以看出:动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。


我们的解题思路:先求子问题,也就是先求出底层的最大值,例如:先求出第4层各数的路径最大值(这里因为第4层是最底层,也就是它本身),然后第3层通过判断自己下面层数的左边和右边(第4层,例如8下面的 16(左)和4(右))谁更大,从而求出第3层各数路径的最大值,有点抽象,给大家一张图来解释一下:


我们从最底下开始看,因为第4层是最底层,所以最大值为它本身,也就是图中的初始化。


分别为16 4 18 10 9。再看第3层,8的左边分别为16和4,因为16最大 故此 以8为根的这个数塔路径最大值为24,同理 以10为根的这个数塔路径最大值为28,以5为根的这个数塔路径最大值为23,以12为根的这个数塔路径最大值为22。以此类推,求出了路径上的数值和最大为60


开始写代码:


首先数塔我们用二维数组存储

public class TTT {
    public static void main(String[] args) {
            int[][] d=new int[5][5];
            d[0][0]=8;
            d[1][0]=12;
            d[2][0]=3;
            d[3][0]=8;
            d[4][0]=16;
            d[1][1]=15;
            d[2][1]=9;
            d[3][1]=10;
            d[4][1]=4;
            d[2][2]=6;
            d[3][2]=5;
            d[4][2]=18;
            d[3][3]=12;
            d[4][3]=10;
            d[4][4]=9;
            //遍历二维数组
            int cnt=0;
            for (int[] row : d) {
                    cnt=0;
                    for (int data : row) {
                            cnt++;
                            System.out.printf("%d\t", data);
                            //当输出的数字等于数组长度时,换行
                            if (cnt==d.length){
                                    System.out.println();
                            }
                    }
            }
    }
}

 


分析:


d[i][j]=Math.max(d[i+1][j]+d[i][j],d[i+1][j+1]+d[i][j]);


表示这个数下面的两个数和自身相加 取一个最大的。


例如:


以8为例


d[i][j]=Math.max(d[i+1][j]+d[i][j],d[i+1][j+1]+d[i][j]);


d[i][j]=Math.max(16+8,4+8)=24

        for (int i= d.length-2;i>0;i--){
            for (int j=0;j<=i;j++){
                d[i][j]=Math.max(d[i+1][j]+d[i][j],d[i+1][j+1]+d[i][j]);
//                System.out.println(d[i][j]);
            }
        }
        System.out.println(Math.max(d[1][0] + d[0][0], d[1][1] + d[0][0]));

因为一开始我们是以倒数第二层的 8 先开始的


所以一开始


i=d.leng-2(也就是8的行数位置索引)


j=0(也就是8的列数位置索引)


完整代码:  

 

public class CountingTower {
    public static void main(String[] args) {
        int[][] d=new int[5][5];
        d[0][0]=8;
        d[1][0]=12;
        d[2][0]=3;
        d[3][0]=8;
        d[4][0]=16;
        d[1][1]=15;
        d[2][1]=9;
        d[3][1]=10;
        d[4][1]=4;
        d[2][2]=6;
        d[3][2]=5;
        d[4][2]=18;
        d[3][3]=12;
        d[4][3]=10;
        d[4][4]=9;
        //遍历二维数组
        int cnt=0;
        for (int[] row : d) {
            cnt=0;
            for (int data : row) {
                cnt++;
                System.out.printf("%d\t", data);
                //当输出的数字等于数组长度时,换行
                if (cnt==d.length){
                    System.out.println();
                }
            }
        }
        for (int i= d.length-2;i>0;i--){
            for (int j=0;j<=i;j++){
                d[i][j]=Math.max(d[i+1][j]+d[i][j],d[i+1][j+1]+d[i][j]);
//                System.out.println(d[i][j]);
            }
        }
        System.out.println(Math.max(d[1][0] + d[0][0], d[1][1] + d[0][0]));
    }
}

相关文章
|
7月前
|
Java
0-1背包问题(Java详解)(动态规划)至少与恰好
0-1背包问题(Java详解)(动态规划)至少与恰好
64 1
【Java每日一题,动态规划,零钱兑换模板题】硬币组合数量
【Java每日一题,动态规划,零钱兑换模板题】硬币组合数量
|
6月前
|
算法 Java 决策智能
Java数据结构与算法:动态规划之背包问题
Java数据结构与算法:动态规划之背包问题
【Java每日一题,动态规划】数字金字塔
【Java每日一题,动态规划】数字金字塔
|
7月前
|
算法 Java
给定一个字符串数组,如何找到其中最长的回文子串? 要求:编写一个Java函数,输入一个字符串数组,输出其中最长的回文子串。要求时间复杂度为O(n^2)。可以考虑使用动态规划或中心扩展的方法来优化算法。
给定一个字符串数组,如何找到其中最长的回文子串? 要求:编写一个Java函数,输入一个字符串数组,输出其中最长的回文子串。要求时间复杂度为O(n^2)。可以考虑使用动态规划或中心扩展的方法来优化算法。
88 1
【Java每日一题,动态规划,Map实现】最长定差子序列
【Java每日一题,动态规划,Map实现】最长定差子序列
【Java每日一题,动态规划】最长定差子序列
【Java每日一题,动态规划】最长定差子序列
|
人工智能 Java BI
打家劫舍系列(力扣198、213、337)Java动态规划
打家劫舍系列(力扣198、213、337)Java动态规划
144 0
买卖股票系列(力扣121、122、123、188、309、714) Java动态规划
使用两个变量,一个变量max来保存截止到当天获得的最大利润,另一个变量min来保存截止到当天股票的最小价格,动态规划即可求出所有的当天价格中,最大的价格
117 0
|
算法 Java
力扣300:最长递增子序列(Java动态规划+双指针)
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
206 0