题目链接:
题解:
显然遇到这种DP题我们要先打暴力,通过读题我们可以快速推出DP式子:
状态:设 d p [ i ] dp[i] dp[i]为前i个人的最大价值
状态转移方程:
设 ( ∑ k = j + 1 i a [ k ] ) = X (\sum_{k = j + 1}^i a[k]) = X (∑k=j+1ia[k])=X
d p [ i ] = m a x ( d p [ j ] + a ∗ X 2 + b ∗ X + c ) dp[i] = max(dp[j] + a * X^2 + b * X + c) dp[i]=max(dp[j]+a∗X2+b∗X+c)
累加我们可以直接前缀和优化,设 ( ∑ k = 1 i a [ k ] ) = S u m i (\sum_{k=1}^i a[k]) = Sum_i (∑k=1ia[k])=Sumi
那么转移方程即可化为: d p [ i ] = m a x ( d p [ j ] + a ∗ ( S u m i − s u m j ) 2 + b ∗ ( S u m i − s u m j ) + c ) dp[i] = max(dp[j] + a * (Sum_i - sum_j)^2 + b *(Sum_i - sum_j) + c) dp[i]=max(dp[j]+a∗(Sumi−sumj)2+b∗(Sumi−sumj)+c)
至此如果你不像作者一样SB把初始化搞错,那么你已经有50分的高分
暴力代码:
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 1000005;
long long n, a, b, c, x[MAXN], sum[MAXN], dp[MAXN];
int main() {
scanf("%lld %lld %lld %lld", &n, &a, &b, &c);
for (int i = 1; i <= n; i++) {
scanf("%lld", &x[i]);
sum[i] = sum[i - 1] + x[i];
dp[i] = -0x7f7f7f7f7f7f7f;
}
for (int i = 1; i <= n; i++) {
for (int j = 0; j < i; j++) {
int X = (sum[i] - sum[j]);
dp[i] = max(dp[i], dp[j] + a * X * X + b * X + c);
}
}
printf("%lld", dp[n]);
}
通过观察式子,发现带有平方以及二次项,并且不定的只有个j,再根据标签我们断定这道题要用斜率优化
那么我们开始推式子