zoukankan      html  css  js  c++  java
  • 【BZOJ 1096】[ZJOI2007]仓库建设

    【链接】 链接
    【题意】

    在这里输入题意

    【题解】

    设f[i]表示在第i个地方设立一个仓库,且前面符合要求的最小花费。 则 $f[i] = min(f[j] + c[i] + dis[i]*(sump[i] - sump[j])-(sumdp[i]-sumdp[j]));$ 其中 sump[]是p[]的前缀和,即$sump[i] = p[1]+p[2]+..+p[i]$ sumdp[]是x[]*p[]的前缀和,即$sumdp[i] = x[1]*p[1]+x[2]*p[2]+...+x[i]*p[i]$ 这个表示j+1..i这一段的所有物品都运输到i这个仓库。 自己用笔写一下就知道了。 显然是个N^2算法。 斜率优化。 设x< y,且y优于x. balabala就能得到 $frac{f[y]+sumdp[y]-(f[x]+sumdp[x])}{sump[y]-sump[x]}< dis[i]$ 又dis是单调递增的。 这是一个经典的斜率优化问题了。

    【错的次数】

    在这里输入错的次数

    【反思】

    在这里输入反思

    【代码】

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    const int N = 1e6;
    
    int n,dl[N+10],h,t;
    ll dis[N+10],p[N+10],c[N+10],sump[N+10],sumdp[N+10];
    ll dp[N+10];
    
    double ju(int x,int y)
    {
        double fenzi = dp[y] + sumdp[y] - (dp[x]+sumdp[x]);
        double fenmu = sump[y] - sump[x];
        return fenzi/fenmu;
    }
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        scanf("%d",&n);
        for (int i = 1;i <= n;i++)
        {
            scanf("%lld%lld%lld",&dis[i],&p[i],&c[i]);
            sump[i] = sump[i-1] + p[i];
            sumdp[i] = sumdp[i-1] + dis[i]*p[i];
        }
    
        for (int i = 1;i <= N;i++) dp[i] = 1e18;
        h = 1,t = 1;
        dl[1] = 0;
        for (int i = 1;i <= n;i++)
        {
            while (h < t && ju(dl[h],dl[h+1])<dis[i]) h++;
            int j = dl[h];
            dp[i] = min(dp[i],dp[j] + c[i] +
                                dis[i]*(sump[i]-sump[j])-(sumdp[i]-sumdp[j]));
            while (h < t && ju(dl[t-1],dl[t]) > ju(dl[t],i)) t--;
            dl[++t] = i;
        }
        printf("%lld
    ",dp[n]);
        return 0;
    }
    
    
  • 相关阅读:
    SpringMVC
    SpringMVC
    SpringMVC
    Spring
    Spring
    值类型和引用类型
    判断字符串的开头和结尾
    二分法(课后)
    验证码
    从1-36中随机出6个不相等的数
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7637996.html
Copyright © 2011-2022 走看看