区间DP模版:
for (int len = 1; len < n; len++) { //操作区间的长度
for (int i = 0, j = len; j <= n; i++, j++) { //始末
//检查是否匹配(非必须)
for (int s = i; s < j; s++) {
//update
}
}
}
如果我们要得知一个大区间的情况,由于它必定是由从多个长度不一的小区间转移而来(转移情况未知),我们可以通过求得多个小区间的情况,从而合并信息,得到大区间。这样的算法复杂度为O(N^3)。
例:石子合并问题
#include
#define min(x, y) (x > y ? y : x)
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 210;
int dp[maxn][maxn];
int sum[maxn];
int a[maxn];
int main(int argc, const char * argv[]) {
int n;
while (~scanf("%d", &n)) {
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
sum[i] = sum[i - 1] + a[i];
}
for (int len = 1; len < n; len++) { //操作区间的长度
for (int i = 1, j = len + 1; j <= n; i++, j++) { //始末
//检查是否匹配(非必须)
dp[i][j] = INF;
for (int s = i; s < j; s++) {
dp[i][j] = min(dp[i][j], dp[i][s] + dp[s + 1][j] + sum[j] - sum[i - 1]);
}
}
}
printf("%d\n", dp[1][n]);
}
return 0;
}
题目总结:https://www.cnblogs.com/123-123/p/5813327.html
平形四边形优化分析:
在动态规划中,经常遇到形如下式的状态转移方程:
m(i,j)=min{m(i,k-1),m(k,j)}+w(i,j)(i≤k≤j)(min也可以改为max)
上述的m(i,j)表示区间[i,j]上的某个最优值。w(i,j)表示在转移时需要额外付出的代价。该方程的时间复杂度为O(N3)
下面我们通过四边形不等式来优化上述方程,首先介绍什么是“区间包含的单调性”和“四边形不等式”
1、区间包含的单调性:如果对于 i≤i' 2、四边形不等式:如果对于 i≤i' 下面给出两个定理: 1、如果上述的 w 函数同时满足区间包含单调性和四边形不等式性质,那么函数 m 也满足四边形不等式性质 我们再定义 s(i,j) 表示 m(i,j) 取得最优值时对应的下标k(即 i≤k≤j 时,k 处的 w 值最大,则 s(i,j)=k)。此时有如下定理 2、假如 m(i,j) 满足四边形不等式,那么 s(i,j) 单调,即 s(i,j)≤s(i,j+1)≤s(i+1,j+1)。 好了,有了上述的两个定理后,我们发现如果w函数满足区间包含单调性和四边形不等式性质,那么有 s(i,j-1)≤s(i,j)≤s(i+1,j) 。 即原来的状态转移方程可以改写为下式: m(i,j)=min{m(i,k-1),m(k,j)}+w(i,j)(s(i,j-1)≤k≤s(i+1,j))(min也可以改为max) 由于这个状态转移方程枚举的是区间长度 L=j-i,而 s(i,j-1) 和 s(i+1,j) 的长度为 L-1,是之前已经计算过的,可以直接调用。 不仅如此,区间的长度最多有n个,对于固定的长度 L,不同的状态也有 n 个,故时间复杂度为 O(N^2),而原来的时间复杂度为 O(N^3),实现了优化! 今后只需要根据方程的形式以及 w 函数是否满足两条性质即可考虑使用四边形不等式来优化了。 例:石子合并#include
(btw,对于石子合并问题,如要求最大值,则不能采用平形四边形优化的方法,为什么我也没想清楚.....如果有人知道了可以在评论区告诉我