数塔—动态规划

    xiaoxiao2021-04-17  39

    数塔(dp_基础)

    在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的: 有如上所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少? 已经告诉你了,这是个DP的题目,你能AC吗? Input 输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间0,990,99内。 Output 对于每个测试实例,输出可能得到的最大和,每个实例的输出占一行。

    Sample Input 1 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 Sample Output 30

    解题思路

    很自然就可以想到暴力搜索的方法但是费时长,会超时暴力搜索是从上向下搜索,那么继续考虑就会想到从下向上把最下面的俩个数字找出最大的加到他上面的那个数把最后一排执行完再依次执行上一行

    具体思路如下

    发表候看到图片看的不太清晰,各位可以放大观看,游览器一般按ctrl + + 初始状态 从下向上比较执行 那么可以看到在第二行第一个存储了左边那部分的较大值和 右边也一样

    第二行的每个元素存储了他下面的的最优子结构 那么只需要比较出第二行的然后加到第一个元素,就是最大的情况了

    代码如下

    # include <cstdio> # include <cstring> # include <algorithm> using namespace std; int a[100][100]; // 用二维数组存储数据 int main() { int C; scanf("%d",&C); while (C--) { memset(a,0,sizeof(a)); //把数组初始化为0 int n; //数塔的高度 scanf("%d",&n); for (int i = 0;i < n;i++) { for(int j = 0;j <= i;j++) { scanf("%d",&a[i][j]); //输入数塔 } } for (int i = n-1;i > 0;i--) { for(int j = 0;j <= i;j++) { a[i-1][j] += max(a[i][j],a[i][j+1]); //状态转移公式 } } printf("%d\n",a[0][0]); } return 0; }

    注意点

    数组的下表从0开始所以要减一所谓的最优子结构就如同该题的一个格子,这个格子一定是代表着他下面到他当前位置的和的最大值重新画了一下图,希望帮到各位。如果觉得我哪里写的不清楚,希望各位评论,指正,感激不尽。 -
    转载请注明原文地址: https://ju.6miu.com/read-673739.html

    最新回复(0)