洛谷Oj-数字三角形-动态规划

来源:互联网 发布:财富证券交易软件 编辑:程序博客网 时间:2024/06/16 23:16

问题描述
观察下面的数字金字塔。
写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的样例中,从7 到 3 到 8 到 7 到 5 的路径产生了最大
输入样例#1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出样例#1
30
AC代码①

int a[1001][1001],dp[1001][1001],max2=-1;//数组a记录数字三角形,dp[i][j]代表从点(1,1)到点(i,j)的路径的最大值int max1(int a,int b){    return a>b?a:b;}int main(){    int i,j,r;    scanf("%d",&r);    for(i=1;i<=r;i++)        for(j=1;j<=i;j++)            scanf("%d",&a[i][j]);//输入数字三角形    for(i=1;i<=r;i++)//从上到下,遍历每一个点        for(j=1;j<=i;j++)        {            if(i==1&&j==1)                dp[i][j]=a[i][j];            else if(j==1)                dp[i][j]=a[i][j]+dp[i-1][j];            else if(j==i)                dp[i][j]=a[i][j]+dp[i-1][j-1];            else                dp[i][j]=a[i][j]+max1(dp[i-1][j],dp[i-1][j-1]);        }    for(j=1;j<=r;j++)//找出最后一行最大的dp[i][j]值        if(dp[r][j]>max2)            max2=dp[r][j];    printf("%d\n",max2);//打印    return 0; }

算法描述:显然,该题目不能用贪心来解决。下面是动态规划递推公式的推导思路:

先从最后一行入手,一般情况下,点(i,j)可通过点(i-1,j)和点(i-1,j-1)到达,因此dp[i][j]=a[i][j]+max1(dp[i-1][j],dp[i-1][j-1][j],dp[i-1][j-1]),前提条件i-1>=1和j-1>=1
再从第一行入手,第一行只有一个数,那么dp[i][j]=a[i][j],前提条件i==1和j==1
再来关注边界上的情况,若在左边界(j==1),那么点(i,j)只能通过点(i-1,j)到达,有dp[i][j]=a[i][j]+dp[i-1][j]
若在右边界(j==i),那么点(i,j)只能通过点(i-1,j-1)到达,有dp[i][j]=a[i][j]+dp[i-1][j-1]
注意别忘了加上a[i][j]
2017/6/14更新
AC代码②

int a[1001][1001],dp[1001][1001];int max1(int a,int b){    return a>b?a:b;}int main(){    int i,j,r;    scanf("%d",&r);    for(i=1;i<=r;i++)        for(j=1;j<=i;j++)            scanf("%d",&a[i][j]);    for(i=r;i>=1;i--)        for(j=1;j<=i;j++)        {            if(i==r)//自下                dp[i][j]=a[i][j];            else//而上                dp[i][j]=a[i][j]+max1(dp[i+1][j],dp[i+1][j+1]);        }    printf("%d\n",dp[1][1]);//打印dp[1][1]    return 0; }
原创粉丝点击