动态规划(待完善)
动态规划
1.子段和问题
问题描述:
给出一段长度为n的整数序列,选出其中连续且非空的一段使得这段和最大。
例如序列:
2 -4 3 -1 2 -4 3
3 -1 2 -4 3
的和是3
3 -1 2
的和是4,是子段和中最大的
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n, a[200005], dp[200005], maxx = -1e9;
signed main() {
cin >> n;
for(int i = 1;i <= n;i ++) {
cin >> a[i];
}
dp[n] = a[n];
maxx = max(maxx, a[n]);
for(int i = n - 1;i >= 1;i --) {
dp[i] = max(a[i] + dp[i + 1], a[i]);
maxx = max(maxx, dp[i]);
}
cout << maxx;
return 0;
}
2. 数字三角形问题
下图所示为一个数字三角形,其中三角形中的数值为整数,现规定从最顶层往下走到底层,每一步可沿左斜线向下或右斜线向下走。
7
3 8
8 1 0
2 7 7 4
要求计算从最顶层走到最底层的一条路径,使得沿着该路径所经过的数字之和最大。
上图给出了n=4时的一个数字三角形。
数据存储与表示:
可以转化为上面的结构用二维数组来存储,数字三角形上的每一个数字对应一个行列号 \(i\),\(j\)。
不难发现,本问题具有
“最优子结构性质”
假设(r,c)为起点的一条最优路线表示为 R(r,c) = (r,c) (r2,c2) (r3,c3)…
最优解表示为 F(r,c)
。
则当 r < n 时,R(r,c)
和 F(r,c)
一定是下面两种情况中的一种:
R(r, c) = (r, c) R(r + 1, c)
F(r, c) = F(r + 1, c) + a[r][c]
R(r, c) = (r, c) R(r + 1, c + 1)
F(r,c) = F(r + 1, c + 1) + a[r][c]
拆、求、和
核心:找到原问题与子问题的关系
核心代码:
for(int j = 1;j <= n;j ++) {
f[n][j] = a[n][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]) + a[i][j];
}
}