斜率优化
如何压缩维数。
dp[i] = max(dp[j] + (s[i] - s[j]) * s[j])
dp[i] = max(dp[j] + s[i] * s[j] - sqr(s[j]));
如果k比j优且k>j
则有s[k] > s[j]
dp[j] + s[i] * s[j] - sqr(s[j]) < dp[k] + s[i] * s[k] - sqr(s[k])
(s[k] - s[j]) * s[i] > dp[j] - dp[k] - sqr(s[j]) + sqr(s[k])
s[i] > (dp[j] - dp[k] - sqr(s[j]) + sqr(s[k])) / (s[k] - s[j])
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100010
using namespace std;
int n, K;
int a[maxn];
long long dp[2][maxn], sqr[maxn], s[maxn];
int cur;
int q[maxn];
double slop(int k, int j){
return (double) (dp[cur][j] - dp[cur][k] - sqr[j] + sqr[k]) / (s[k] - s[j]);
}
void Transform(int x){
int l = 1, r = 0, j;
for(int i = x; i <= n; i ++){
while(l < r && slop(q[l], q[l + 1]) < s[i])
l ++;
j = q[l];
dp[cur ^ 1][i] = dp[cur][j] + s[i] * s[j] - sqr[j];
while(l < r && slop(q[r - 1], q[r]) > slop(q[r], i))
r --;
q[++ r] = i;
}
}
int main(){
scanf("%d%d", &n, &K);
int x, tot = 0;
for(int i = 1; i <= n; i ++){
scanf("%d", &x);
if(x)a[++ tot] = x;
}
n = tot;
for(int i = 1; i <= n; i ++){
s[i] = s[i - 1] + a[i];
sqr[i] = s[i] * s[i];
}
for(int i = 1; i <= K; i ++){
Transform(i);
cur ^= 1;
}
printf("%lld\n", dp[cur][n]);
return 0;
}

本文介绍了一种使用斜率优化技术来减少动态规划中状态数量的方法。通过数学推导,我们展示了如何更新状态转移方程,并给出了一个具体的实现案例。该案例使用C++编程语言,通过维护一个单调队列来确保每次状态转移都是最优的。
917

被折叠的 条评论
为什么被折叠?



