动态规划——数塔问题

动态规划经典题目——数塔问题

一、题目

数塔问题 :要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?

二、解题思路

     动态规划解题思路可详见另一篇文章。数塔中元素用二维数组a[][]表示

①定义状态

由题意可设dp[i][j]为第i层的第j个顶点到底层经过的最大数字和。

②定义状态转移方程

大家知道动态规划满足无后向性,即:每个阶段的决策仅受之前决策的影响,但是不影响之后各阶段的决策。所以我们可以从后往前推出状态转移方程(逆向思维),dp[0][0]等于第1层第1个数字到底层经过的最大数字和,它等于dp[1][0] + a[0][0]或dp[1][1] + a[0][0]中的最大的数值。我们可以公式化,得到如下状态转换方程:

         dp[i][j] = max( dp[i+1][j] + dp[i+1][j+1] ) + a[i][j]

③确定边界

由状态定义我们可以得出当数字在最底层时,它到最底层就是数字本身,即可得出dp[i][j] = a[i][j] (0≤i,j≤N)

三、代码编写


 
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define N 5
  4. #define max(a,b) ((a>b)?a:b)
  5. int main()
  6. {
  7. //保存数塔元素
  8. int a[N][N] = { { 9, 0, 0, 0, 0},
  9. { 12, 15, 0, 0, 0},
  10. { 10, 6, 8, 0, 0},
  11. { 2, 18, 9, 5, 0},
  12. { 19, 7, 10, 4, 16}};
  13. //dp[i][j]为第i层的第j个顶点到底层经过的最大数字和
  14. int dp[N][N] = { 0};
  15. //确定边界数值
  16. int i,j;
  17. for(i= 0;i < N;i++){
  18. dp[N -1][i] = a[N -1][i];
  19. }
  20. //核心算法
  21. for(i=N -2;i >= 0;i--){
  22. for(j= 0; j < i+ 1 ;j++){
  23. dp[i][j] = max(dp[i+ 1][j],dp[i+ 1][j+ 1]) + a[i][j];
  24. }
  25. }
  26. printf( "DP矩阵为:\n");
  27. for(i= 0;i < N;i++){
  28. for(j= 0; j <= i ;j++){
  29. printf( "%d ",dp[i][j]);
  30. }
  31. printf( "\n");
  32. }
  33. printf( "顶层到底层的经过的最大数字和为:%d",dp[ 0][ 0]);
  34. return 0;
  35. }

四、运行结果

五、总结

动态规划需要满足无后向性,可用逆向思维推出状态转化方程,动态规划解题方法可详见另一篇文章

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值