zoukankan      html  css  js  c++  java
  • 数字三角形问题

    描述:给定一个由n 行数字组成的数字三角形(例如下图)。输出从三角形的顶至底的一条路径,使该路径经过的数字总和最大。

    (红色路径表示最优路径,结果为9+3+8+7+5 = 32)

    算法基本思路:

    显然用一个二维数组rec[0..n-1][0..n-1]可以保存该三角形作为输入(用二维数组对角线以下的位置保存三角形)。

    对于任意rec[i][j],我们可以定义一个表m[i][j] 来表示以rec[i][j]作为当前路径的终点所得到的最优值。

    对于m[i][j],要到达这个数字,必须经过前面的某个数字,可以通过计算前面的最优解来构造m[i][j]的最优解。

    求解m[i][j]的最优解,可以通过子集的最优解构造,满足最优子结构,可以用动态规划。

    1.求路径数字之和的最大值;

    如前所述,这里的rec[i][j]有三种情况,

    (1)rec[i][j]为行首即rec[i][0],那么要到达rec[i][0],只能经过rec[i-1][0],则m[i][0] = m[i-1][0] + rec[i][0];

    (2)rec[i][j]为行尾即rec[i][i],那么要到达rec[i][i],只能经过rec[i-1][i-1],则m[i][i] = m[i-1][i-1] + rec[i][i];

    (3)rec[i][j]为中部元素,此时到达rec[i][j]有两种方式,经过rec[i-1][j-1]或rec[i-1][j],则m[i][j] = max{m[i-1][j-1] + rec[i][j], m[i-1][j] + rec[i][j]}。

    初始化m[0][0] = rec[0][0],自底向上构造表,可以得到以每个数字为终点的路径最优值。

    此时,只需遍历以最后一行的数字为终点的各个最优值,取其最大值m[n-1][k],即是整个三角形的最优值。

    2.获取整个构造路径。

    在1.的基础上,添加表pre[i][j] 表示到达 rec[i][j] 的数字的上一个数字在定位,-1表示是rec[i-1][j-1],1表示是rec[i][j]。

    然后以pre[n-1][k]为起点,逆向构造整条路径直至到达rec[0][0]即可。

    public class RecMaxNum{
    
        public static int getRecMaxNum(int[][] rec){
            /*
            m[i][j]: the max value path which is ended of rec[i][j]
            pre[i][j]: the note of pre value index
            */
            int n = rec.length;
            int[][] m = new int[n][n];
            int[][] pre = new int[n][n];
            //init
            m[0][0] = rec[0][0];
            //dynamic programming
            for(int i = 1; i < n; i ++){
                m[i][0] = m[i-1][0] + rec[i][0];
                pre[i][0] = 1;
                for(int j = 1; j < i; j ++){
                    if(m[i-1][j] + rec[i][j] < m[i-1][j-1] + rec[i][j]){
                        m[i][j] = m[i-1][j-1] + rec[i][j];
                        pre[i][j] = -1;
                    }
                    else{
                        m[i][j] = m[i-1][j] + rec[i][j];
                        pre[i][j] = 1;
                    }
                }
                m[i][i] = m[i-1][i-1] + rec[i][i];
                pre[i][i] = -1;
            }
            int k = 0;
            for(int j = 1; j < n; j ++){
                if(m[n-1][k] < m[n-1][j]){
                    k = j;
                }
            }
            //build the path
            StringBuffer s = new StringBuffer("");
            for(int i = n-1, j = k; i >= 0 && j >= 0;){
                s.insert(0, Integer.toString(rec[i][j]) + " ");
                if(pre[i][j] == -1){
                    i --;
                    j --;
                }
                else{
                    i --;
                }
            }
            System.out.println(s);
            return m[n-1][k];
        }
        
        public static void main(String[] args) {
            int[][] rec = new int[5][5];
            for(int i = 0; i < 5; i ++){
                for(int j = 0; j <= i; j ++){
                    rec[i][j] = (int)(Math.random() * 10);
                    System.out.print(rec[i][j] + " ");
                }
                System.out.println();
            }
            System.out.println(getRecMaxNum(rec));
        }
    
    }
    Java
  • 相关阅读:
    centos下安装mycat
    centos下安装MySQL5.7
    centos下yum安装wget失败
    开心消消乐刷金币
    myBatis获取批量插入数据的主键id
    nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)
    Mac下安装JDK 6
    VI下删除所有内容
    Mac下lombok无法安装到eclipse mars
    WEB-INF目录下的文件访问权限
  • 原文地址:https://www.cnblogs.com/7hat/p/3464100.html
Copyright © 2011-2022 走看看