有一个三角形数阵,行数和列数相等,第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\n",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\n",b[0][0]);
}
}
可以看到,对于这个程序,即使有100行,也只需要运算4950次,将数组 b 填满,就可以得到答案。多用dfs就会发现,
用dfs很容易时间超限,这时候,就需要用其他算法将其代替,所以,最好是在一开始就决定是否要用dfs,以免浪费时间!!