POJ1163-The Triangle

Description

7
3   8
8   1   0
2   7   4   4
4   5   2   6   5

(Figure 1)

Figure 1 shows a number triangle. Write a program that calculates the highest sum of numbers passed on a route that starts at the top and ends somewhere on the base. Each step can go either diagonally down to the left or diagonally down to the right. 

Input

Your program is to read from standard input. The first line contains one integer N: the number of rows in the triangle. The following N lines describe the data of the triangle. The number of rows in the triangle is > 1 but <= 100. The numbers in the triangle, all integers, are between 0 and 99.

Output

Your program is to write to standard output. The highest sum is written as an integer.

Sample Input

5
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5

Sample Output

30

 

 

 

很简单的一道题,直接调用递归函数去解决。

输入数据,然后输出调用的递归函数就OK了。

int main()

int main()
{
       scanf("%d",&n);
       for(int i=1;i<=n;++i)
       {
           for(int j=1;j<=i;++j)
           {
               scanf("%d",&a[i][j]);
           }
       }
       printf("%d\n",poj(1,1));
    return 0;
}

poj()

int poj(int x,int y)
{
    //现在是递归的使用
    //如果说到达最下面的那一行,直接输出
    if(x==n)
        return a[x][y];
    int num1=poj(x+1,y);//这个代表的是左边的数字
    int num2=poj(x+1,y+1);//这个代表的是右边的数字

    return max(num1,num2)+a[x][y];


}

用这种方法很容易得到了结果

但是

提交后是时间超时。

为什么超时?因为在计算的时候重复计算了!!!!时间复杂度是2的n次方,这是一个非常大的数,大到就算是宇宙毁灭也计算不出来结果。

 

如果说每次在计算的时候把这个值给保存下来,那么以后计算的时候可以直接使用,这个时候的时间复杂度为O(n*n);

下面是数字三角形的记忆递归型动规程序:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=105;//最大的数据
int n;
int a[maxn][maxn];
int maxsum[maxn][maxn];
int poj(int x,int y)
{
    if(maxsum[x][y]!=-1)
        return maxsum[x][y];
    //现在是递归的使用
    //如果说到达最下面的那一行,直接输出
    if(x==n)
        return maxsum[x][y]=a[x][y];
    int num1=poj(x+1,y);//这个代表的是左边的数字
    int num2=poj(x+1,y+1);//这个代表的是右边的数字
    return maxsum[x][y]=max(num1,num2)+a[x][y];
}
int main()
{
       scanf("%d",&n);
       for(int i=1;i<=n;++i)
       {
           for(int j=1;j<=i;++j)
           {
               scanf("%d",&a[i][j]);
               maxsum[i][j]=-1;
           }
       }
       printf("%d\n",poj(1,1));
    return 0;
}

不过,我们不用写递归程序,用循环递推也可以解决。

从最底层开始,一层层往上推

这个时候问题来了,每层在向上走的时候,下面的数字已经没有用了,那么我们就可以用以为数组来表示。

用一维数组记录每一行出现的数字的大小,那是不是也可以用数组a来表示呢?

答案是肯定的,从底层开始,一层层向上相加,最后就是答案。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=105;//最大的数据
int n,*maxsum;
int a[maxn][maxn];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=i;++j)
        scanf("%d",&a[i][j]);
    maxsum=a[n];
    for(int i=n-1;i>=1;--i)
        for(int j=1;j<=i;++j)
        maxsum[j]=max(maxsum[j],maxsum[j+1])+a[i][j];
    printf("%d\n",maxsum[1]);
    return 0;
}

 

以底层的为数组的初始值,然后向上相加,直到到达最高点。

maxsum=a[n]

关键点就是maxsum[j]=max(maxsum[j],maxsum[j+1])+a[i][j];

这里的意思就是说,把最大的值赋值给数组左边的元素,因为随着数组下标的减少,右边的值已经不能用了。

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值