算法了解
动态规划基本思想
动态规划主要的思想有以下几点:
- 将复杂问题拆分为一个个子问题,再由子问题推算出原问题
- 将重复使用的量记录下来(类似于记忆化)
一个例题了解动态规划
动态规划五部曲
很多人“学会”了动态规划就是背过代码,照葫芦画瓢。一遇到变形题就不会了,所以,想要真正掌握动规,需要掌握动态规划五部曲才行:
- 定义状态(即确定f数组的含义)
- 确认状态转移方程(即递推式)
- 初始化f数组
- 确认循环顺序
- 举例推导验证
例题解析
来看一道例题:P1216 数字三角形
我们按照动态规划五部曲解决此题。
定义状态
这道题定义状态没什么难度,定义f[i][j]为从第i行第j个数到最后一行的最大价值。
确认状态转移方程
首先思考:f[i][j]如何得来?很明显,对于可选的两条路径,选取最大值即可。所以状态转移方程为f[i][j]+=max(f[i+1][j],f[i+1][j+1])。之所以是+=,因为还需要加上本身价值,故为+=。
初始化数组
这道题因为需要加上本身价值,上面用的是价值,所以用输入的三角形初始化即可。
确认循环顺序
由于每一个推导依赖于下一行,所以显然要从下往上推导。
举例推导验证
留给读者自己验证。
代码
确认了以上五点,代码基本可以得出:
#include<iostream>
using namespace std;
int f[1100][1100],n;
int main(){
cin >> n;
for (int i = 1;i <= n;++i){
for (int j = 1;j <= i;++j) cin >> f[i][j];
}
for (int i = n - 1;i >= 1;--i){
for (int j = 1;j <= i;++j) f[i][j] += max(f[i + 1][j],f[i + 1][j + 1]);
}
cout << f[1][1];
return 0;
}
本文使用 文章同步助手 同步

