题面
题解
跟$\mbox{Gloid}$爷做的一道神仙区间$dp$题。
设$f[l][r][x][y]$为取区间$[l..r]$,剩下的最大值为$x$,剩下的最小值为$y$,且右端点$r$一定还没有发的最小代价。
特别的,设$f[l][r][0][0]$为取完区间$[l..r]$的最小代价。
转移时,枚举中间点$d$,有$$f[i][j][min(x,w[j])][max(y,w[j])]=min(f[i][j][min(x,w[j])][max(y,w[j])],f[i][d-1][x][y]+f[d][j-1][0][0])$$
对于某区间,最后一次的转移需要特判,$$f[i][j][0][0]=min(f[i][j][0][0],f[i][j][x][y]+a+b*(y-x)*(y-x))$$
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ri register int #define N 55 #define LL long long using namespace std; int n,a,b; int w[N],nw[N]; LL f[N][N][N][N]; int main() { cin>>n; cin>>a>>b; for (ri i=1;i<=n;i++) cin>>w[i],nw[i]=w[i]; sort(nw+1,nw+n+1); int t=unique(nw+1,nw+n+1)-nw-1; for (ri i=1;i<=n;i++) w[i]=lower_bound(nw+1,nw+t+1,w[i])-nw; memset(f,0x3f,sizeof(f)); for (ri i=1;i<=n+1;i++) { f[i][i-1][0][0]=0; for (ri x=1;x<=t;x++) for (ri y=x;y<=t;y++) f[i][i-1][x][y]=0; } for (ri k=1;k<=n;k++) for (ri i=1;i<=n-k+1;i++) { int j=i+k-1; for (ri x=1;x<=t;x++) for (ri y=x;y<=t;y++) for (ri d=i;d<=j;d++) f[i][j][min(x,w[j])][max(y,w[j])]=min(f[i][j][min(x,w[j])][max(y,w[j])],f[i][d-1][x][y]+f[d][j-1][0][0]); for (ri x=1;x<=t;x++) for (ri y=x;y<=t;y++) f[i][j][0][0]=min(f[i][j][0][0],f[i][j][x][y]+a+b*(nw[y]-nw[x])*(nw[y]-nw[x])); } cout<<f[1][n][0][0]<<endl; return 0; }