• 仓库建设-斜率优化DP


    ZJOI2007仓库建设

    讲一个比较呆一点的做法:

    设f[i][1]表示后i个点且i点建仓库的最优解,f[i][0]表示后i个点且i点不建仓库的最优解。

    那么显然可以从后往前DP:

    f[i][0]=mini<j<=n{f[j][1]+∑i<=k<j(X[j]-X[k])*P[j]};

    f[i][1]=mini<j<=n{f[i+1][0],f[i+1][1]}+C[i];

    令S[j]=∑i<=k<j(X[j]-X[k])*P[k]。

    则S[j]=∑i<=k<j(X[j]*P[k]-X[k]*P[k])=∑i<=k<jX[j]*P[k]-∑i<=k<jX[k]*P[k]=X[j]*∑i<=k<jP[k]-∑i<=k<jX[k]*P[k]。

    不妨令A[x]=X[x]*P[x]。

    那么S[j]可以用后缀和表示为:S=X[j]*(sumP[i]-sumP[j])-(sumA[i]-sumA[j])。         

    所以f[i][0]=min{f[j][1]+X[j]*(sufP[i]-sufP[j])-(sufA[i]-sufA[j])} 。

    把式子化成一次函数可得:

    f[j]-X[j]*sufP[j]+sufA[j]=-sufP[i]*X[j]+sufA[i]+f[i]

    从后往前维护一个斜率单调递减的下凸壳即可。

     

    需要注意的是,每次应先转移好fi

    因为y中含有f[i],没转移好f[i]会影响i入队时去尾操作。

    #include<bits/stdc++.h>
    #define RG register
    #define IL inline
    #define DB double 
    #define int long long
    using namespace std;
    
    IL int gi() {
        RG int x=0,w=0; char ch=0;
        while (ch<'0'||ch>'9') {if (ch=='-') w=1;ch=getchar();}
        while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
        return w?-x:x;
    }
    
    const int N=1e6+10;
    
    int l,r,q[N];
    int n,P[N],X[N],C[N],A[N],sufA[N],sufP[N],f[N][2];
    
    IL DB Y(int x) {return (DB)f[x][1]-X[x]*sufP[x]+sufA[x];}
    IL DB slope(int x,int y) {return (Y(x)-Y(y))/(DB)(X[x]-X[y])*1.0;}
    
    signed main ()
    {
        RG int i,j;
        n=gi();
        for (i=1;i<=n;++i)
            X[i]=gi(),P[i]=gi(),C[i]=gi(),A[i]=P[i]*X[i];
        for (i=n;i>=1;--i)
            sufP[i]=sufP[i+1]+P[i],sufA[i]=sufA[i+1]+A[i];
        memset(f,0x3f,sizeof(f));
        l=r=1,q[1]=n,f[n][1]=C[n];
        for (i=n-1;i>=1;--i) {
            f[i][1]=min(f[i+1][0],f[i+1][1])+C[i];
            /*for (j=i+1;j<=n;++j)
              f[i][0]=min(f[i][0],f[j][1]+X[j]*(sufP[i]-sufP[j])-(sufA[i]-sufA[j]));
              //f[j][1]-X[j]*sufP[j]+sufA[j]=-sufP[i]*X[j]+sufA[i]+f[i][0];*/
            while (l<r&&slope(q[l],q[l+1])>=(DB)-sufP[i]) ++l;
            f[i][0]=f[q[l]][1]+X[q[l]]*(sufP[i]-sufP[q[l]])-(sufA[i]-sufA[q[l]]);
            while (l<r&&slope(i,q[r])>=slope(q[r],q[r-1])) --r;
            q[++r]=i;
        }
        printf("%lld
    ",min(f[1][1],f[1][0]));
        return 0;
    }
    BY BHLLX
  • 相关阅读:
    ASP.NET Zero--后端应用程序
    ASP.NET Zero--前期要求
    ASP.NET Zero--解决方案结构(层)
    ASP.NET Zero--开发指南
    Pos终端中的主密钥、工作密钥、pin密钥、mac密钥
    location.origin不兼容IE8解决方案
    一些常用的meta标签
    c#核心基础-委托
    springBoot项目启动去掉多余的启动日志
    如何发行自己的TRC20代币,并上线JustSwap去中心化交易所
  • 原文地址:https://www.cnblogs.com/Bhllx/p/10368232.html
Copyright © 2020-2023  润新知