• 仓库建设


    容易想到,我们必须在最低点也就是第n个点建设一个仓库。由此想到这样设状态:f[i]表示仅处理1~i的工厂的最小花费。

    找到一个j<i,在j处建工厂,从j+1到i-1的都运到i处,那么推出状转方程:f[i]=min{f[j]+c[i]+p[k]*(x[i]-x[k])},k从i+1到j-1

    预处理两个前缀和,设sp为p的前缀和,spx为p*x的前缀和。

    可以推出简化版的N^2的状转方程:f[i]=min{f[j]+c[i]+x[i]*(sp[i-1]-sp[j])-spx[i-1]+spx[j]}

    写成一次函数的形式:f[j]+spx[j]=x[i]*sp[j]+f[i]-c[i]-x[i]*sp[i-1]+spx[i-1],其中y=f[j]+spx[j],k=x[i],x=sp[j],b=f[i]-c[i]-x[i]*sp[i-1]+spx[i-1]

    数据保证了x[i]单调递增,非常好!!!

    看代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int maxn=1000000+10;
    int c[maxn],x[maxn],p[maxn],q[maxn];
    int sp[maxn],spx[maxn],f[maxn],n;
    inline int yval(int a,int b){
        return f[b]-f[a]+spx[b]-spx[a];
    }
    inline int xval(int a,int b){
        return sp[b]-sp[a];
    }
    signed main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            scanf("%lld%lld%lld",&x[i],&p[i],&c[i]);
            sp[i]=sp[i-1]+p[i];
            spx[i]=spx[i-1]+p[i]*x[i];
        }
        memset(f,0x3f,sizeof(f));
        f[0]=0;
        int l=1,r=1;
        q[l]=0;
        for(int i=1;i<=n;i++){
            while(l<r&&yval(q[l],q[l+1])<=xval(q[l],q[l+1])*x[i])l++;
            f[i]=f[q[l]]+c[i]+x[i]*(sp[i-1]-sp[q[l]])-spx[i-1]+spx[q[l]];
            while(l<r&&yval(q[r-1],q[r])*xval(q[r],i)>=xval(q[r-1],q[r])*yval(q[r],i))r--;
            q[++r]=i;
        }
        printf("%lld
    ",f[n]);
        return 0;
    }
  • 相关阅读:
    PHPStorm 支持 Element UI 语法提示
    npm
    谷歌浏览器插件
    RBAC
    git 知识点
    Laradock ppa加速
    vscode插件
    临时解决执行 Composer Install 返回 Killed 的问题
    单例设计模式(3种实现方式)
    log4j.properties 详解与配置步骤
  • 原文地址:https://www.cnblogs.com/syzf2222/p/12386805.html
Copyright © 2020-2023  润新知