LOJ P2292 BZOJ P4897「THUSC2016」成绩单【区间DP】【离散化】

又是一道神仙题,我还是太菜了不看题解完全写不出来,其实想到了怎么定状态之后还是比较容易推下去的。

首先思考一下数据范围:n50,而最极端的时间复杂度是:O(n5),所以我们在定状态的时候就不要担心数组维数过大,放心去做吧。

g[i][j]表示消除区间[i,j]的最小代价。

f[l][r][a][b]表示消除区间[l,r]并且最后一次消除区间的最小值为a,最大值为b的最小代价。

考虑区间合并:
g[i][j]={f[i][k][a][b]+g[k+1][j]+A+B(ba)2}

然后我们枚举f的第三维和第四维来进行更新:
f[i][j][min(a,w[j])][max(b,w[j])]=min\{f[i][k][a][b]+g[k+1][j-1]\}

最后的答案就为:g[1][n]

注意的地方,f的大小是50*50*1000*1000B=2500MB->MLE,但是很显然第三维第四维可以离散化来优化空间:50^4B=6.25MB->AC

#include <bits/stdc++.h>
#define For(I,L,R) for(int I=(L);I<=(R);I++)
#define ForDown(I,L,R) for(int I=(L);I>=(R);I--)
using namespace std;

inline int Read(){
    int X=0;char CH=getchar();bool F=0;
    while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
    while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
    return F?-X:X;
}

const int Max=55;
const int Inf=1e9;
int N,A,B,W[Max],Id[Max];
int G[Max][Max],F[Max][Max][Max][Max];

#define Update(X,Y) ((X)=((X)>(Y))?(Y):(X))

int main(){
    N=Read();
    A=Read(),B=Read();

    For(I,1,N) W[I]=Id[I]=Read();

    sort(W+1,W+1+N);
    int Len=unique(W+1,W+1+N)-W-1;
    For(I,1,N) Id[I]=lower_bound(W+1,W+Len+1,Id[I])-W;

    For(I,1,N) For(J,1,N) G[I][J]=Inf;
    For(I,1,N) For(J,1,N) For(K,1,N) For(L,1,N) F[I][J][K][L]=Inf;

    For(I,1,N) F[I][I][Id[I]][Id[I]]=G[I+1][I]=0;G[1][0]=0;

    ForDown(L,N,1) For(R,L,N) For(I,1,Len)
    For(J,I,Len){
        if(F[L][R][I][J]==Inf) continue;
        For(K,R+1,N) Update(F[L][K][min(I,Id[K])][max(J,Id[K])],F[L][R][I][J]+G[R+1][K-1]);
        For(K,R,N) Update(G[L][K],F[L][R][I][J]+G[R+1][K]+A+B*(W[J]-W[I])*(W[J]-W[I]));
    }

    printf("%d",G[1][N]);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/81638952