P1216 [USACO1.5] [IOI1994]数字三角形 Number Triangles
前言
没有食言,今天就来做动态规划的题目。首先也还是从入门题开始做起,这题难度不高,也是检验是否掌握动态规划基本思想的题目。做得出来说明动态规划思想就差不多了。做两三题动态规划基础题,我们就去做更难的动态规划。
题目
题目描述
观察下面的数字金字塔。
写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。
在上面的样例中,从 7 → 3 → 8 → 7 → 5 7 \to 3 \to 8 \to 7 \to 5 7→3→8→7→5 的路径产生了最大权值。
输入格式
第一个行一个正整数 r r r ,表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
输出格式
单独的一行,包含那个可能得到的最大的和。
样例 #1
样例输入 #1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
样例输出 #1
30
提示
【数据范围】
对于
100
%
100\%
100% 的数据,
1
≤
r
≤
1000
1\le r \le 1000
1≤r≤1000,所有输入在
[
0
,
100
]
[0,100]
[0,100] 范围内。
题目翻译来自NOCOW。
题目分析
经典的动态规划的题目。我理解的动态规划的题目就是把局部结果保存到数组里,然后就不需要再进行重复的计算。那么这题也是。
不用脑子的方法就是暴力枚举,写循环。但是你会发现前面的求和需要算很多遍,就类比斐波那契数列。所以我们想到将每个数组到这的最优解(就是到这里的路径最大和)保存在另一个数组b的相同的位置。
当然需要注意的是边缘的上一步只能是上一层的边缘,只有中间部分才有两个上一步。
注意事项
1.maxx不能和max函数同名否则会报错
2.三角形边长部分(最外面的人字框部分需要单独处理)
代码
#include<iostream>
using namespace std;
int a[1007][1007]={0},b[1007][1007]={0};
//a用来存放原始数据,b用来存放目前最优解
int main(){
int n,maxx=0;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cin>>a[i][j];
}
}
b[1][1]=a[1][1];
for(int i=2;i<=n;i++){
b[i][1]=b[i-1][1]+a[i][1];
b[i][i]=b[i-1][i-1]+a[i][i];
}
for(int i=3;i<=n;i++){
for(int j=2;j<i;j++){
b[i][j]=max(b[i-1][j-1],b[i-1][j])+a[i][j];
}
}
for(int i=1;i<=n;i++){
if(b[n][i]>maxx)
maxx=b[n][i];
}
cout<<maxx<<endl;
return 0;
}
后话
跟着我的进度刷题,给个点赞收藏+关注!
题目来源
USACO Training Section 1.5
IOI1994 Day1T1
洛谷链接