动态规划入门
动态规划 是编程解题的一种重要手段。1951 年美国数学家 R.Bellman 等人,根据一类多阶段问题的特点,把多
阶段决策问题变换为一系列互相联系的单阶段问题,然后逐个加以解决。与此同时,他提出了解决这类问题的“最
优化原理”,从而创建了解决最优化问题的一种新方法:动态规划。
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于
一个值,我们希望找到具有最优值的解。
我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结
果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。
动态规划的基本概念:
阶段:把所给问题的求解过程恰当地分成若干个相互联系的阶段,以便于求解。过程不同,阶段数就可能不
同。描述阶段的变量称为阶段变量,常用 k 表示。阶段的划分,一般是根据时间和空间的自然特征来划分,
但要便于把问题的过程转化为多阶段决策的过程。
状态:状态表示每个阶段开始面临的自然状况或客观条件,它不以人们的主观意志为转移,也称为不可控因
素。通常一个阶段有若干个状态,状态通常可以用一个或一组数来描述,称为状态变量。
决策:表示当过程处于某一阶段的某个状态时,可以做出不同的决定,从而确定下一阶段的状态,这种决定
称为决策。不同的决策对应着不同的数值,描述决策的变量称决策变量。
状态转移方程:动态规划中本阶段的状态往往是上一阶段的状态和上一阶段的决策的结果,由第 i 段的状态
f(i) ,和决策 u(i) 来确定第 i + 1 段的状态。状态转移表示为 F(i + 1) = T(f(i), u(i)),称为状态转移方程。
策略:各个阶段决策确定后,整个问题的决策序列就构成了一个策略,对每个实际问题,可供选择的策略有
一定范围,称为允许策略集合。允许策略集合中达到最优效果的策略称为最优策略。
下面来一道例题:
数塔问题
Description
观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。
在上面的样例中,从13到8到26到15到24的路径产生了最大的和86。
Input
第一个行包含R(1≤ R≤1000),表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
所有的被供应的整数是非负的且不大于100。
Output
单独的一行,包含那个可能得到的最大的和。
Sample Input 1
5
13
11 8
12 7 26
6 14 15 8
12 7 13 24 11
Sample Output 1
86
分析这道题可以从上一个问题,推断下一个问题。那么就可以选择从第一开始搜也就是这个样例当中的第一行第一个“13”开始,那么它下一行 i 的也就可以从 i - 1 的第 j 个和第 j - 1 找到第 i , j 个的最大值那么转移方程就可以得到 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1]) + a[i][j]; 那么此时的dp[n][1 ~ n] 中的最大值就是此题的解;
参考代码:
#include <bits/stdc++.h>
using namespace std;
int r;
int a[1001][1001];
int dp[1001][1001];
int main() {
cin >> r;
for(int i = 1; i <= r; i++) {
for(int j = 1; j <= i; j++) {
cin >> a[i][j];
}
}
for(int i = 1; i <= r; i++) {
for(int j = 1; j <= i; j++) {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1]) + a[i][j];//从j - 1 和 j 来解决问题
}
}
int max1 = -999;//设置最大值
for(int i = 1; i <= r; i++){
if(dp[r][i] > max1){
max1 = dp[r][i];//寻找最大的那一个
}
}
cout << max1 << endl;
return 0;
}
那么现在这个题也解决了;
点击
哈哈