洛谷 U279551 数字三角形
题目描述
给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输入格式
第一行包含整数 n
,表示数字三角形的层数
接下来 n
行,每行包含若干整数,其中第 i
行表示数字三角形第 i
层包含的整数。
输出格式
输出一个整数,表示最大的路径数字和。
样例 #1
样例输入 #1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
样例输出 #1
30
提示
1 ≤ n ≤ 500
−10000 ≤ 三角形中的整数 ≤ 10000
题解
未AC版 40分
数字三角形
#include<iostream>
using namespace std;
int a[510][510] = {0};
int cnt = 0; //当前路径
int ans = -1e9; //最大路径
int n;
void dfs(int x , int y) // (x , y)代表坐标,也就是所走路径,x为横坐标,y为纵坐标
{
if(x == n)
{
if(cnt > ans)
ans = cnt;
return;
}
cnt += a[x+1][y];
dfs(x+1 , y);
cnt -= a[x+1][y];
cnt += a[x+1][y+1];
dfs(x+1 , y+1);
cnt -= a[x+1][y+1];
}
int main()
{
cin >> n;
for(int i = 1 ; i <= n ; i++)
{
for(int j = 1 ; j <= i ; j++)
cin >> a[i][j];
}
cnt = a[1][1];
dfs(1 , 1);
cout << ans;
return 0;
}
思路:用一个二维数组a[n][n] 来存数字三角形,不难看出每一次移动都是向下或者向右下移动。
我们设计一个自定义递归函数dfs,使得每次移动都向下移动,记录当前路径和,然后回退,再向右下移动,记录当前路径和,然后再回退,递归函数中每一次x = = n ,都代表走完了一条路径。当整个递归函数结束时,代表所有路径都被走完。
我们定义了两个变量cnt,ans。用cnt代表某一条路径的长度,用ans储存最大的路径长度。每当x = = n 时,比较当前路径长度 cnt 与 最大路径长度 ans 作比较,若 cnt > ans ,则更新 ans 的值等于 cnt 。当整个递归函数结束时,就得到了所有路径中最大的路径长度。
不足
采用这种方法,在会出现不必要的计算,以及递归会增加程序运行的时间,当数据量较大时,就有可能出现超时的情况。
AC版
数字三角形
#include<iostream>
using namespace std;
const int N = 510 , inf = -1e9;
int a[N][N] = {0};
int cnt[N][N]; //用于存储到达a[i][j]时的最大路径cnt[i][j];
int main()
{
int n;
cin >> n;
for(int i = 1 ; i <= n ; i++)
{
for(int j = 1 ; j <= i ; j++)
{
cin >> a[i][j];
}
}
for(int i = 0 ; i <= n ; i++)
{
for(int j = 0 ; j <= n ; j++)
{
cnt[i][j] = inf;
}
}
cnt[1][1] = a[1][1];
for(int i = 2 ; i <= n ; i++)
{
for(int j = 1 ; j <= i ; j++)
cnt[i][j] = max(cnt[i-1][j-1] , cnt[i-1][j]) + a[i][j];
}
int ans = inf; //用ans来存储最大的路程
for(int j = 1 ; j <= n ; j++) mlans = max(cnt[n][j] , ans);
cout << ans;
return 0;
}
思路: 用一个二维数组cnt[n][n] 来存储到达 a[i][j] 时的最大路径,用 ans 来存储到达第n层时最大路径,用cnt[n][1] ~cnt[n][n] 依次与 ans 进行比较,便能得到最大路径ans。