动态规划法之数塔问题

 动态规划法是将带求解问题分解成 若干个子问题,若子问题还能分解成多个子问题还需进行分解,最后对所有字问题进行求解。

在数塔问题中,子问题就是求每一层的子塔的最大和,以书上例子为例

顶层为8的5层数塔的子问题是顶层为12的4层数塔和顶层为15的4层数塔,以此类推,顶层为12的4层数塔的子问题是顶层为3的3层数塔和顶层为9的3层数塔以及顶层为6的3层数塔,就按照这个逻辑可以得出数塔的最小子问题是数塔最后一层的值。解决了子问题是为了解决比子问题层次高一点的子问题。例如解决顶层为3的子塔问题是为了解决顶层为12这个子塔的问题,最终求得答案的解。

解决数塔问题,是要求数塔问题的最大和路径和最大和,解决一个问题想到用什么存储方式来存储数据和结果更为合适,这里我用二维数组来存储数塔的所有数据data[][],每一层代表一行,每个数据都在某一行的某一列。因为你要记录每一个节点的最大路径,路径是指向的是一个数,所以最好也用二维数组来表示path[][].

最开始最小子问题中最大和是最后一层的数据,最后一层的每一个节点都是一个子塔,最大和就是他们本身。解决完最后一层的问题然后解决倒数第二层,就拿倒数第二层的8来举例子,解决这个子问题要先比较他的两个子塔的最大和大小,把最大的子塔和和8相加得到最新的maxAdd,至于怎么比较就是data[4][0],data[4][1]相比,8为data[3][0],这里可以发现子塔的列索引是节点的列索引和节点的列索引+1,解决完一个子问题要更新maxAdd和path这里用的C实现的

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i,j;
    int data[100][100];
    int maxAdd[100][100];
    int path[100][100];
    int n;
    printf("请输入数塔的层数  ");
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        for(j=0;j<=i;j++)
        {
            scanf("%d",&data[i][j]);
        }
    }
    for(j=0;j<i;j++)
    {
        maxAdd[n-1][j]=data[n-1][j];
    }
    for(i=n-2;i>=0;i--)
    {
        for(j=0;j<=i;j++)
        {
            if(maxAdd[i+1][j]>maxAdd[i+1][j+1])
            {
                maxAdd[i][j]=maxAdd[i+1][j]+data[i][j];
                path[i][j]=j;
            }
            else
            {
                maxAdd[i][j]=maxAdd[i+1][j+1]+data[i][j];
                path[i][j]=j+1;
            }
        }
    }
    printf("sum=%d\n",maxAdd[0][0]);
    printf("%d",data[0][0]);
    j=path[0][0];
    for(i=1;i<n;i++)
    {
        printf("--->%d",data[i][j]);
        j=path[i][j];
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值