动态规划——数字塔

题目描述:

第i行有i个数字,每次只能向下或向正右方走,求和最大的路径的和

3

1    5

8    4    3

2    6    7    9

6    2    3    5    1

与贪心算法不同的是,因为每次只能向下或向右走,每次走的方向会导致后面结果发生改变。用动态规划的思想解决。仔细分析可以得到数字与左边数字和上边数字的数量关系,用另一个数组去记录每一个数字的最优结果,遍历全部数据即可得结果。

优化方案:不必每个数字的最优结果都要记录,只需要用一个层数大小的数组dp记录每一层的情况即可。每次从左到右遍历下一层时,最开头的数的最大和由上一层开头数字最大和得来,此时dp[0]+=a[i]。然后下一个数据要么由新的dp[i]得来,要么由旧的dp[i]得来。

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <queue>
#include <stack>
#include <string.h>
#include <math.h>
#include <algorithm>

int n;
int tower[40010],value[40010],st[1000];

int main(){
    scanf("%d",&n);
    for(int i=0;i*(i+1)/2<=n;i++)
        st[i]=i*(i+1)/2;
    for(int i=1;i<=n;i++){
        scanf("%d",&tower[i]);
    }

    int maxn=-1;
    value[1]=tower[1];
    for(int i=2;i*(i+1)/2<=n;i++){
        value[st[i-1]+1]=value[st[i-2]+1]+tower[st[i-1]+1];
        if(value[st[i-1]+1]>maxn)maxn=value[st[i-1]+1];
        for(int j=2;j<i;j++){
            int t;
            if(value[j-1+st[i-1]]>value[j+st[i-2]]){
                t=value[j-1+st[i-1]];
            }
            else{
                t=value[j+st[i-2]];
            }
            printf("+++%d %d %d %d %d",tower[j+st[i-1]],t,i,j,st[i]);
            value[j+st[i-1]]=t+tower[st[i-1]+j];
            if(value[j+st[i-1]]>maxn)
                maxn=value[j+st[i-1]];
        }
        value[st[i]]=value[st[i]-1]+tower[st[i]];
        if(value[st[i]]>maxn)maxn=value[st[i]];
    }
    for(int i=1;i<=n;i++)
        printf("%d**\n",value[i]);
    printf("%d\n",maxn);
}
发布了62 篇原创文章 · 获赞 7 · 访问量 1649

猜你喜欢

转载自blog.csdn.net/qq_43331910/article/details/99972599