Yet Another Minimization Problem(CF1637D)

Des

You are given two arrays a and b , both of length n .

You can perform the following operation any number of times (possibly zero): select an index i ( 1in ) and swap ai and bi .

Let's define the cost of the array a as i=1nj=i+1n(ai+aj)2 . Similarly, the cost of the array b is i=1nj=i+1n(bi+bj)2 .

Your task is to minimize the total cost of two arrays.

Sol

由题意可知,要求的值是在将任意的 aibi 交换的前提下,最小的

i=1nj=i+1n(ai+aj)2+i=1nj=i+1n(bi+bj)2

那么,由该式可以推出

=i=1nj=i+1nai2+i=1nj=i+1naj2+i=1nj=i+1n2aiaj+i=1nj=i+1nbi2+i=1nj=i+1nbj2+i=1nj=i+1n2bibj=(n1)(i=1nai+i=1nbi)+i=1nj=i+1n2aiaj+i=1nj=i+1n2bibj=[(n1)(i=1nai+i=1nbi)]+2[i=1nai(j=i+1naj)+i=1nbi(j=i+1nbj)]=[(n1)(i=1nai+i=1nbi)]+2[i=1nai(j=1i1aj)+i=1nbi(j=1i1bj)]

可以发现其中的 (n1)(i=1nai+i=1nbi) 是作为一个定值出现的,所以我们只需要将 [i=1nai(j=1i1aj)+i=1nbi(j=1i1bj)] 最小化即可。

这一点,利用动规解决。

在由第 i1 个状态向第 i 个状态转移的时候,我们无法确定的是 j=i+1naij=i+1nbi 的值(因为其中可能存在交换)。

那么因为考虑到 i=1nai 的值并不大,所以可以将 i=1nai 加入状态。

又因为交换的为 aibi,可以发现在相同范围内的区间和的和(即 i=lrai+bi)也是一个定值,那么就可以求出对应的 b 的区间的和。

此时,我们设计状态为 f(i,j) 表示为考虑前 i 位,k=1iak=j 时的最小值,

那么对于状态的转移,

si=k=1i(ai+bi) 的值。

  • 如果 aibi 不进行交换,那么此时的

j=ai+k=1i1ak,k=1i1ak=k=1iakai=jai,k=1i1bk=si1k=1i1ak=si(jai)

则状态转移为

min{f(i1,jai)+ai×(jai)+bi×(si1j+ai)}

  • 如果 aibi 进行交换,那么此时的

j=bi+k=1i1akk=1i1ak=jbi,k=1i1bk=si1k=1i=1ak=si1(jbi)

则状态转移为(此时的 aibi 交换)

min{f(i1,jbi)+bi×(jbi)+ai×(si1j+bi)}

CODE

void solve() {
    ans=minn=0;
    memset(f,0x7f7f7f,sizeof(f));
    f[0][0]=0;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) {
        cin>>b[i];
        k[i]=k[i-1]+max(a[i],b[i]);
        sum[i]=sum[i-1]+a[i]+b[i];
        ans+=a[i]*a[i]+b[i]*b[i];
    }
    ans*=(n-1);
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=k[i];j++) {
            if (j-a[i]>=0 && sum[i-1]-j+a[i]>=0) {
                f[i][j]=min(f[i][j],f[i-1][j-a[i]]+a[i]*(j-a[i])+b[i]*(sum[i-1]-j+a[i]));
            }
            if (j-b[i]>=0 && sum[i-1]-j+b[i]>=0){
                f[i][j]=min(f[i][j],f[i-1][j-b[i]]+b[i]*(j-b[i])+a[i]*(sum[i-1]-j+b[i]));
            }
        }
    }
    minn=1e9+7;
    for(int j=1;j<=k[n];j++){
        minn=min(minn,f[n][j]);
    }
    cout<<ans+2*minn<<'\n';
}
posted @   Ciaxin  阅读(20)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示