三角形问题

    有一个三角形数阵,行数和列数相等,第n行有n个数字,现在从上顶点,也就是第一行第一列出发,只能向左下或者向右下走到下一行,一直走到末尾,求怎么能使路径上的数字和最大,求这个最大值。

第一行是一个数m,代表测试次数;对于每一次测试:第一行是一个数n(1<n<100),代表这个三角形数阵有n行,接着是n行的一个三角形数阵(对于每一个数都有1<Aij<100)。

例如:输入:

        1

        5

        7

        3   8

        8   1   0

        2   7   4   4

        4   5   2   6   5

       输出:

        30

对于这个问题,很容易想到用dfs,一条路径一条路径的找下去,最后得到那个最大值,所以写出了以下的程序:

#include<stdio.h>
int a[100][100]={0},i,j,k,m,n;
int max=0,ans;
void dfs(int x,int y, int ans)
{
    ans+=a[x][y];
    if(x==n-1)
    {
        if(max<ans)
        max=ans;
    }
    else
    {
        dfs(x+1,y,ans);
        dfs(x+1,y+1,ans);
    }
}
main()
{
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            for(j=0;j<=i;j++)
           {
                scanf("%d",&a[i][j]);
           }
        }
        dfs(0,0,0);
        printf("%d
",max);
     }
}

 

    然后带入样例,发现是对的,但是,忽略了一点:时间。对,如果测试一个有99行的样例,那么会发现结果会弹出的非常慢,为什么呢?

用数学方法算算就会知道:99行的样例一共会有2的98次方个路径,这么多路径,对于计算机来说也是较为庞大的,更何况要去找那个最大值,

就更不容易了!

    那怎么去做这个题呢?既然要找最大值,那肯定走到每一个位置都有一个最大值,从头去找那个最大值不好找那何不直接从最后一行退回去找呢?

除了存放数阵的数组外,再定义一个数组,同样有n行,但是每个位置存放着倒着走走到当前的最大值,这样一层一层往上,这个数组的第一行的那个数

肯定就是所有路径的最大值了;

例如:

对于:

        7                        的路径最大值数阵为:          30

        3   8                                                  23        21

        8   1   0                                              20        13       10

        2   7   4   4                                          7         12       10       10

        4   5   2   6   5                                      4          5       2        6        5      

        用这个思路,很容易就写出了以下的程序:

#include<stdio.h>
int a[100][100]={0},b[100][100],i,j,k,m,n;
int max(int x,int y)
{
    if(x>y)
    return x;
    else
    return y;
}
void d(int n)
{
    for(i=0;i<n;i++)
        b[n-1][i]=a[n-1][i];
    for(i=n-2;i>=0;i--)
    {
        for(j=i;j>=0;j--)
        b[i][j]=a[i][j]+max(b[i+1][j],b[i+1][j+1]);
     }
}
main()
{
    scanf("%d",&m);
    while(m--)
    {
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        for(j=0;j<=i;j++)
        {
            scanf("%d",&a[i][j]);
        }
     }
     d(n);
    printf("%d
",b[0][0]);
    }
}

 

可以看到,对于这个程序,即使有100行,也只需要运算4950次,将数组   b    填满,就可以得到答案。多用dfs就会发现,

用dfs很容易时间超限,这时候,就需要用其他算法将其代替。

原文地址:https://www.cnblogs.com/xujunming/p/6159986.html