我在提交此问题时超出时间限制
问题:
让我们考虑一个数字三角形,其中一个数字出现在第一行,两个数字出现在第二行,三个出现在第三行,等等。开发一个程序,计算最大的总和从顶部到底部出现在路径上的数字,以便:
在每条路径上,下一个数字位于下面的行中,更准确地说是 直接在下方或下方以及右侧的一个地方;
行数严格为正,但小于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))));
}
答案 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 + 5
,6
的路径为1 + 3 + 6
。您的代码分别计算每个路径,因此1 + 3
将被计算两次。如果保存该结果,您将摆脱大部分不必要的计算。
你怎么能存储这样的结果?好吧,1 + 3
是计算到达3
的路径,所以将它存储在那里。如果多个路径可以达到一个数字(比如5
)该怎么办?
5
可以通过1 + 2 + 5
或1 + 3 + 5
。
通过5
的任何路径如果首先通过3
,将会产生更高的结果,因此只记住此路径(并忽略{{1}的路径,它现在没用了。)
所以,作为算法:
对于每一行,从第1行开始(不是第一行,但第二行):对于每个条目:计算上面留下的条目的最大值(如果可用)和正上方(如果可用)并存储结果+条目的值作为条目的新值。然后,找到最后一行的最大值。