为什么我的时间限制超过了?

时间:2016-01-30 20:24:40

标签: c++

我在提交此问题时超出时间限制

问题:

让我们考虑一个数字三角形,其中一个数字出现在第一行,两个数字出现在第二行,三个出现在第三行,等等。开发一个程序,计算最大的总和从顶部到底部出现在路径上的数字,以便:

在每条路径上,下一个数字位于下面的行中,更准确地说是 直接在下方或下方以及右侧的一个地方;

行数严格为正,但小于100

所有数字都是O和99之间的正整数。

我的代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int trian(int i,int j);
    long long int n,a[100][100];
    int main()
    {
        long long int t,i,j,v,k;
        scanf("%lld",&t);
        for(i=0;i<t;i++)
        {
            scanf("%lld",&n);
            for(j=0;j<n;j++)
            {
                for(k=0;k<j+1;k++)
                {
                    scanf("%lld",&a[j][k]);
                }
            } 
            v=trian(0,0);
            printf("%lld\n",v);
        }
    }
    int trian(int i,int j)
    {
        if(i>=n)
        return 0;
        else
        return (a[i][j]+(std::max(trian(i+1,j),trian(i+1,j+1))));
    } 

1 个答案:

答案 0 :(得分:0)

  

为什么我的时间限制超过了?

考虑这个三角形(忽略数字):

1
2 3

这里有2条可能的路径。让我们添加一行:

1
2 3
4 5 6

4只能通过直接在上方结束的路径到达,5有两条可以到达的路径,6只能从之前结束的路径到达留在它上面。我们现在有4条可能的路径。另一行:

1
2 3
4 5 6
7 8 9 0

这8条可能的路径。你看到一个模式吗?让我们从7开始直接描述1的路径:

D = DOWN
R = DOWN AND RIGHT

DDD

0的(单个)路径:

RRR

由于在每一步中你都走了一排,你只能选择两种可能性number of rows - 1次,从而给你:

2^(number of rows - 1) possible paths

有100行,很多。您的代码尝试分别计算每个路径。假设计算1路径需要1纳秒(这将是快速的),计算它们将花费超过2 * 10^16 。嗯,......

  

超出时间限制

所以你现在知道你不能只计算每一条可能的路径并采取最大化。主要问题如下:

1
2 3
4 5 6

5的一条路径为1 + 3 + 56的路径为1 + 3 + 6。您的代码分别计算每个路径,因此1 + 3将被计算两次。如果保存该结果,您将摆脱大部分不必要的计算。

你怎么能存储这样的结果?好吧,1 + 3是计算到达3的路径,所以将它存储在那里。如果多个路径可以达到一个数字(比如5)该怎么办?

5可以通过1 + 2 + 51 + 3 + 5

与您联系

通过5的任何路径如果首先通过3,将会产生更高的结果,因此只记住此路径(并忽略{{1}的路径,它现在没用了。)

所以,作为算法:

对于每一行,从第1行开始(不是第一行,但第二行):对于每个条目:计算上面留下的条目的最大值(如果可用)和正上方(如果可用)并存储结果+条目的值作为条目的新值。然后,找到最后一行的最大值。