THUSC 成绩单

题目链接:Click here

Solution:

我们设\(f[l][r][x][y]\)表示在原区间\(l\sim r\) 内还未被取走的值最大为\(x\)最小为\(y\)时的代价,这里我们只考虑区间\(l \sim r\)

我们再用\(g[l][r]\)表示将原区间$l\sim r $里的数全部取完的最小代价,则易得转移式
\[ f[l][r][min(x,a[r])][max(y,a[x])]=min(f[l][r][min(x,a[r])][max(y,a[x])],f[l][r-1][x][y])\\ f[l][r][x][y]=min(f[l][r][x][y],f[l][k][x][y]+g[k+1][r]) \]
其中第一个转移表示直接从区间\(l\sim r-1\)转移过来,因为\(r\)没被取走,所以只要更新取值区间就行了

第二个转移表示枚举一个\(k\),从\(k\)断开,\(k\)之后的全部取完,\(k\)之前的取值区间为\(x\,y\),最后的答案即为\(g[1][n]\)

Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,A,B,a[51],b[51];
int f[51][51][51][51],g[51][51];
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
signed main(){
    n=read();A=read(),B=read();
    memset(f,0x3f,sizeof(f));
    memset(g,0x3f,sizeof(g));
    for(int i=1;i<=n;i++) a[i]=read(),b[i]=a[i];
    sort(b+1,b+n+1);m=unique(b+1,b+n+1)-b-1;
    for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+m+1,a[i])-b;
    for(int i=1;i<=n;i++) f[i][i][a[i]][a[i]]=0,g[i][i]=A;
    for(int len=1;len<=n;len++){
        for(int l=1;l+len-1<=n;l++){
            int r=l+len-1;
            for(int x=1;x<=m;x++)
                for(int y=x;y<=m;y++){
                    f[l][r][min(a[r],x)][max(a[r],y)]=min(f[l][r][min(a[r],x)][max(a[r],y)],f[l][r-1][x][y]);
                    for(int k=l;k<r;k++)
                        f[l][r][x][y]=min(f[l][r][x][y],f[l][k][x][y]+g[k+1][r]);
                }
            for(int x=1;x<=m;x++)
                for(int y=x;y<=m;y++)
                    g[l][r]=min(g[l][r],f[l][r][x][y]+A+B*(b[y]-b[x])*(b[y]-b[x]));
        }
    }printf("%lld\n",g[1][n]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/NLDQY/p/11665803.html