洛谷:P1216 [USACO1.5] [IOI1994]数字三角形 Number Triangles(DP 入门)

[USACO1.5] [IOI1994]数字三角形 Number Triangles

题目描述

观察下面的数字金字塔。

写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。

洛谷:P1216 [USACO1.5] [IOI1994]数字三角形 Number Triangles(DP 入门)_第1张图片

在上面的样例中,从 7 → 3 → 8 → 7 → 5 7 \to 3 \to 8 \to 7 \to 5 73875 的路径产生了最大权值。

输入格式

第一个行一个正整数 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 1r1000,所有输入在 [ 0 , 100 ] [0,100] [0,100] 范围内。

题目翻译来自NOCOW。

USACO Training Section 1.5

IOI1994 Day1T1

知识:

本题是动态规划,即给定一个问题,我们把它拆成一个个子问题,直到子问题可以直接解决。然后把子问题的答案保存起来,以减少重复计算。再根据子问题答案反推,得出原问题解的一种方法。

动态规划入门思路: dfs暴力 --> 记忆化搜索 --> 递推(转化成公式)

1dfs > 2记忆化搜索 > 3逆序递推 > 4顺序递推 > 5优化空间 !

记忆化搜索 = 暴力dfs + 记录答案

递归的过程:
“递” 的过程是: 分解子问题的过程。

“归” 的过程才是: 产生答案的过程。

“递” —> 自顶向下, “归” —> 自底向上 , 其中 “底” 是 递归搜索树 的底是最小的子问题的答案。

写出递推公式的方法:

递推 的公式 = dfs 向下 递归 的公式

递推 数组的初始值 = 递归 的边界(出口)

递归是向下,递推是向上,递推是小问题之和,还要算出最优的小问题

一般写的都是逆序递推(这里的逆是对层数而言的),从最高层要往上推,所以是+1,答案在上面,如果要写正序递推的话,改一下顺序就行了(-1),答案在下面。

思路:

本题要求走过的路径值最大,我们可以从最上方出发,把子问题拆成一步可以往正下或者下右走,然后将值返回当前记录答案的数组,不断遍历之后,最上方的数组就是答案。

逆推代码:

#include 
using namespace std;
int n;
vector<vector<int>> v(1010,vector<int> (1010));
vector<vector<int>> ans(1010,vector<int> (1010));
int main() {
	cin >> n;
	for(int i=0;i<n;i++){
		for(int j=0;j<=i;j++){
			cin >> v[i][j];
		}
	}
	for(int i=n-1;i>=0;i--){
		for(int j=0;j<n;j++){
			ans[i][j]=max(ans[i+1][j],ans[i+1][j+1])+v[i][j];
		}
	}
	cout << ans[0][0];
	return 0;
}

你可能感兴趣的:(深度优先,算法,动态规划)