P5336
[THUSC2016]成绩单
区间 DP。
我一开始想了一个奇怪的做法,定义
我们定义状态
然后我们发现这个转移似乎只在
但借助
这样就可以接起来了。
最后处理
关于初始化,直接处理长度为 1 的区间即可,即
显然
时间复杂度
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const ll N=50;
ll n,a,b,totw;
ll g[N+5][N+5],f[N+5][N+5][N+5][N+5];
ll w[N+5],uqw[N+5];
inline ll read() {
ll ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-f;ch=getchar();}
while(ch>='0'&&ch<='9') {ret=(ret<<3)+(ret<<1)+ch-'0';ch=getchar();}
return ret*f;
}
void write(ll x) {
static char buf[22];static ll len=-1;
if(x>=0) {
do{buf[++len]=x%10+48;x/=10;}while(x);
}
else {
putchar('-');
do{buf[++len]=-(x%10)+48;x/=10;}while(x);
}
while(len>=0) putchar(buf[len--]);
}
int main() {
n=read();
a=read();b=read();
memset(f,0x3f,sizeof(f));memset(g,0x3f,sizeof(g));
for(ll i=1;i<=n;i++) {
w[i]=read();uqw[++totw]=w[i];
}
sort(uqw+1,uqw+totw+1);totw=unique(uqw+1,uqw+totw+1)-uqw-1;
for(ll i=1;i<=n;i++) {
w[i]=lower_bound(uqw+1,uqw+totw+1,w[i])-uqw;
f[i][i][w[i]][w[i]]=0;g[i][i]=a;
}
for(ll i=2;i<=n;i++) {
for(ll j=1;j+i-1<=n;j++) {
for(ll l=1;l<=totw;l++) {
for(ll r=l;r<=totw;r++) {
f[j][j+i-1][min(l,w[j+i-1])][max(r,w[j+i-1])]=
min(f[j][j+i-1][min(l,w[j+i-1])][max(r,w[j+i-1])],
f[j][j+i-2][l][r]);
for(ll k=j;k<j+i-1;k++) {
f[j][j+i-1][l][r]=min(f[j][j+i-1][l][r],
f[j][k][l][r]+g[k+1][j+i-1]);
}
}
}
for(ll l=1;l<=totw;l++) {
for(ll r=l;r<=totw;r++) {
g[j][j+i-1]=min(g[j][j+i-1],
f[j][j+i-1][l][r]+a+b*(uqw[r]-uqw[l])*(uqw[r]-uqw[l]));
}
}
}
}
write(g[1][n]);
return 0;
}