• [ZJOI2007] 仓库建设


    传送门:>HERE<

    题意:有n个地点,每个地点有货物P[i]个,距离起点(地点0)的距离为x[i]。在每个地点建立仓库需要费用c[i],现在需要在某些地点建设仓库,从而将货物转移到仓库里。规定只能从编号小的地点转移到编号大的地点,同时转移的费用的是路程*货物数量。求最小的总费用(总费用=建设费用+转移费用)

    解题思路:

      动态规划+斜率优化

      令$f[i]$表示在地点i建设仓库,并且1~i的货物都已经全部处理好了。可以得到$O(n^2)$的状态转移方程$$f[i] = Min{f[j] + sumlimits_{k=1}^{i-1}(x[i]-x[k])*p[k] + c[i]}$$

      维护前缀和P[i]为数组p的前缀和,g[i]为x[i]*p[i]的前缀和。得到$$f[i] = f[j] + (P[i-1]-P[j])*x[i] - (g[i-1]-g[j]) + c[i]$$

    转化为一次函数形式$$f[j]+P[i-1]*x[i]-g[i-1]+g[j]+c[i] = x[i] * P[j] + f[i]            Longleftrightarrow           y = kx + b$$

    去掉没用的项,得$$f[j]+g[j] = x[i] * P[j] + f[i]$$

      坐标为$(P[j], f[j]+g[j])$

      正常做就行了

      这题主要难在f[i]的构想上,斜率优化这一步并没有什么坑点

    Code

      long long

    /*By QiXingzhi*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #define  r  read()
    #define  Max(a,b)  (((a)>(b)) ? (a) : (b))
    #define  Min(a,b)  (((a)<(b)) ? (a) : (b))
    using namespace std;
    typedef long long ll;
    #define int long long
    const int MAXN = 1000010;
    const int INF = 1061109567;
    inline int read(){
        int x = 0; int w = 1; register int c = getchar();
        while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
        if(c == '-') w = -1, c = getchar();
        while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar();
        return x * w;
    }
    int n,m,h,t;
    int x[MAXN],p[MAXN],c[MAXN],g[MAXN],P[MAXN],q[MAXN],f[MAXN];
    inline double X(int i){ return P[i]; }
    inline double Y(int i){ return f[i] + g[i]; }
    inline double Slope(int i, int j){ return (double)(Y(i)-Y(j)) / (double)(X(i)-X(j)); }
    main(){
    //    freopen(".in","r",stdin);
        n = r;
        for(int i = 1; i <= n; ++i){
            x[i] = r, p[i] = r, c[i] = r;
            P[i] = P[i-1] + p[i];
            g[i] = g[i-1] + x[i] * p[i];
        }
        for(int i = 1; i <= n; ++i){
            while(h<t && Slope(q[h],q[h+1]) < x[i]) ++h;
            f[i] = f[q[h]] + (P[i-1]-P[q[h]])*x[i] - g[i-1] + g[q[h]] + c[i];
            while(h<t && Slope(q[t-1],q[t]) > Slope(q[t],i)) --t;
            q[++t] = i;
        }
        printf("%lld", f[n]);
        return 0;
    }
  • 相关阅读:
    uni-app 苹果内购支付及获取苹果支付成功信息
    nginx强制使用https访问(http跳转到https)
    最新IOS审核被拒原因TOP10 | 附带解决方法
    ethercat PREEMPT SMP
    client-go workqueue
    k8s apiserver 重启失败
    cni flannel iptables -t filter -D FORWARD -j REJECT --reject-with icmp-host-prohibited
    nginx configmap
    golang yaml LoadYAML
    not found: manifest unknown: manifest unknown
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9356933.html
Copyright © 2020-2023  润新知