动态规划解决树的最大权重路径问题

问题描述:将一个由N行数字组成的三角形,如下图实列,设计一个算法,计算处三角形的由顶值至底的
  一条路径,使得该路径经过的数字总和是最大的(最大权重)

                             7
                          3   8
                        8   1   0
                      2   7   4   4
                    4   5   2   6   5

动态规划的思路:这倒题目,只要知道有递归这个神奇东西的同学,肯定会想要用DFS深度优先搜索去逐层遍历每个节点,直至到底端,再不断的回溯...选择....再回溯....,问题是,这种深度优先搜索的方法,耗时非常的大,性能不高,特别是当给出的数据很大的时候,根本就解不出来。。。因为有很多点重复的进行递归回溯,导致求解问题的时间非常糟糕。如果有一个数据结构,可以记录每个状态,那就可以节省重复的工作从而提升效率。

用动态规划的办法解决这道题是非常高效的,使用该方法的前提是要找到初始状态以及状态转义方程。运用递归求解的时候经常是从上往下依次递归,不妨我们倒过来思考一下,可不可以从下往上递推回去呢??这道题要求我们求一条权重最大的路径,我的想法是,首先定义一个状态数组dp[x][y]去记录每个节点的累计权重(即该节点的子节点中,权重较大的一条路径的权重之和),其中x代表第x行,y是第x行中的第y列。其次呢,我们要选择初始状态,既然从最后一层开始向上递推,且最后层的节点没有子节点,故这一层中的dp[x][y]就相当于自身的权重值。确定了初始状态后,我们就需要确定递推公式了!很容易的可以知道,树中的每个父节点有两个子节点,要确定最大权重路径,就要从两个子节点中比较他们的dp值,选择其中较大的并加上父节点自身的权重,得到的值即为父节点的dp值。。。依次类推,直到到达顶点,结束递推,而顶点的dp[0][0]即为最大权重路径的总值。故此递推公式为:dp[x][y]=(dp[x+1][y+1]+map[x][y]>dp[x+1][y]+map[x][y]?dp[x+1][y+1]+map[x][y]:dp[x+1][y]+map[x][y]) 。其中map[x][y]即为该节点的权重!

实现代码:

  1. public class TreeProblem {
  2.     public static void main(String[] args) {
  3.         int [][]map=
  4.             {{7,0,0,0,0},
  5.              {3,8,0,0,0},
  6.              {8,1,0,0,0},
  7.              {2,7,4,4,0},
  8.              {4,5,2,6,5}
  9.              };
  10.         //总共有多少行
  11.         int n=map.length;
  12.         //保存每个节点的累计权重的状态数组
  13.         int [][]dp=new int[n][n];
  14.         //自底向上,一次递推处一条到顶点最大权重的路径,第一步要初始化最底层的dp状态
  15.         for(int i=0;i<n;i++){
  16.             /*map[n-1][i];其中n-1代表树中的最后一排,i则是第i个子节点
  17.               因为最后排没有它自己的子节点了,故此dp[n-1][i]即是map[n-1][i]
  18.             */
  19.             dp[n-1][i]=map[n-1][i];
  20.         }
  21.         //开始从下往上一次递推到顶点处,顶点的累积值dp[0][0]即为最大权重
  22.         //x=n-2即为从树中的倒数第二行开始(因为倒数第一行的dp值全知道且没有子节点)
  23.         for(int x=n-2;x>=0;x--){
  24.             for(int y=0;y<=x;y++){
  25.                 //状态转义方程
  26.                 dp[x][y]=(dp[x+1][y+1]+map[x][y]>dp[x+1][y]+map[x][y]?
  27.                                    dp[x+1][y+1]+map[x][y]:
  28.                                        dp[x+1][y]+map[x][y]
  29.                           );
  30.                 
  31.             }
  32.         }
  33.         
  34.         System.out.println(dp[0][0]);
  35.     }
  36. }
     

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值