C++/python描述 898. 数字三角形 (四种实现方法)

  大家好,我叫亓官劼(qí guān jié )


题目

给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。

        7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

输入格式

第一行包含整数n,表示数字三角形的层数。

接下来n行,每行包含若干整数,其中第 i 行表示数字三角形第 i 层包含的整数。

输出格式

输出一个整数,表示最大的路径数字和。

数据范围

1≤n≤500,
−10000≤三角形中的整数≤10000

输入样例:

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

输出样例:

30

给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。

        7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

输入格式

第一行包含整数n,表示数字三角形的层数。

接下来n行,每行包含若干整数,其中第 i 行表示数字三角形第 i 层包含的整数。

输出格式

输出一个整数,表示最大的路径数字和。

数据范围

1≤n≤500,
−10000≤三角形中的整数≤10000

输入样例:

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

输出样例:

30

题解思路

这题可以使用动态规划的思想,第一行是起点,不需要动,从第二行开始,路径和最大值​​a[i][j]​​分为三种情况:

  • 第i行第1个数只能由第i-1行第1个数向左下走到
  • 第i行第i个数只能由第i-1行第i-1个数向右下走到
  • 第i行第2n-1个数,可以由第i-1行第2n-2个数走到,每次取其中最大值,状态转移方程为:​​a[i][j] += max(a[i-1][j-1],a[i-1][j])​

C++实现为:

#include<iostream>
using namespace std;
int main(){
int n;
cin>>n;
int a[505][505];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= i; j++)
scanf("%d",&a[i][j]);
for(int i = 2; i <= n; i++){
// 第i行第1个数只能由第i-1行第1个数向左下走到
a[i][1] += a[i-1][1];
// 第i行第2~n-1个数,可以由第i-1行第2~n-2个数走到
// 从第二行开始向下走,最大值a[i][j] += max(a[i-1][j-1],a[i-1][j])
for(int j = 2; j <= i-1; j++){
a[i][j] += max(a[i-1][j-1],a[i-1][j]);
}
// 第i行第i个数只能由第i-1行第i-1个数向右下走到
a[i][i] += a[i-1][i-1];
}
int ans = a[n][1];
for(int i = 1; i <= n; i++){
if(a[n][i] > ans)
ans = a[n][i];
}

cout<<ans;
return 0;
}

C++实现二:倒推实现

#include<iostream>
using namespace std;
int main(){
int n;
cin>>n;
// 开辟空间,赋值为0
int a[505][505] = {0};
for(int i = 1; i <= n; i++)
for(int j = 1; j <= i; j++)
scanf("%d",&a[i][j]);
// 倒序dp,这样写放简单,不需要考虑边界问题
// 从第n行向第1行倒推
// 状态转移方程:a[i][j] += max(a[i+1][j],a[i+1][j+1])
for(int i = n-1; i >= 1; i--){
for(int j = 1; j <= i; j++){
a[i][j] += max(a[i+1][j],a[i+1][j+1]);
}
}
// 倒推到第一行,则a[1][1]即最大值
cout<<a[1][1];
return 0;
}

Python实现一:

= int(input())
# store存储输入数据
store = []
# 输入
for i in range(0,n):
# 每次读入一行,int类型
temp = list(map(int, input().split()))
store.append(temp)
# 注意这里是从0开始存储的,与C++实现时不同
for i in range(1,n):
# 第i行第0个数只能由第i-1行第0个数向左下走到
store[i][0] += store[i-1][0]
# 第i行第1~i-1个数,可以由第i-1行第1~i-1个数走到
# 从第二行开始向下走,最大值store[i][j] += max(store[i-1][j-1],store[i-1][j])
for j in range(1,i):
store[i][j] += max(store[i-1][j-1],store[i-1][j])
# 第i行第i+1个数只能由第i-1行第i个数向右下走到
store[i][i] += store[i-1][i-1]
# 记录最大值即返回值
ans = store[n-1][0]
for item in store[n-1]:
if item > ans:
ans = item
print(ans)

Python实现二:倒推实现

# 自下往上做更方便

N = int(input())
# 多开一行,方便实现在1-N上存储,看起来更方便
dp = [[0]*(N+1) for _ in range(N+2)]
s = [[0]]
for i in range(N):
a = list(map(int, input().split()))
s.append(a)
for i in range(N, 0, -1):
for j in range(i):
dp[i][j] = max(dp[i+1][j], dp[i+1][j+1])+s[i][j]
print(dp[1][0])