zoukankan      html  css  js  c++  java
  • BZOJ 1096 [ZJOI2007]仓库建设:斜率优化dp

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1096

    题意:

      有n个工厂,从左往右排成一排,分别编号1到n。

      每个工厂里有p[i]件产品,到1号工厂的距离为x[i],在此处建一个仓库的花费为c[i]。

      现在你需要建造一些仓库,使得所有产品都被运送到仓库中来。

      产品只能从左往右运输。每一件产品运输一个单位距离的花费为1。

      问你最小总花费(运输费 + 建仓库花费)。

     

    题解:

      表示状态:

        dp[i]表示在工厂i建了一个仓库,并且仓库1 to i中的产品都已经被运到仓库中了,此时的最小总花费。

      找出答案:

        ans = dp[n]

        因为无论如何都必须在工厂n处建一个仓库。

      如何转移:

        dp[i] = min dp[j] + ∑(p[k]*(x[i]-x[k])) + c[i]

        (j < i, k = j+1 to i)

        定义前缀和数组:sp[i] = ∑ p[j], s[i] = ∑(x[j]*p[j])

        (j = 1 to i)

        则原转移方程可化简为:

          dp[i] = min dp[j] + x[i]*(sp[i]-sp[j]) - s[i] + s[j] + c[i]

      边界条件:

        dp[0] = 0

      斜率优化:

        设j < k,且k的决策更优。

        则有:dp[j] + x[i]*(sp[i]-sp[j]) + s[j]> dp[k] + x[i]*(sp[i]-sp[k]) + s[k]

        整理得:(dp[j]+s[j]-dp[k]-s[k]) / (sp[j]-sp[k]) < x[i]

        (注意:因为sp[j]-sp[k]<0,所以除过来之后不等式要变号)

        所以slope(i,j) = (dp[i]+s[i]-dp[j]-s[j]) / (sp[i]-sp[j])

        由于x[i]递增,所以用单调队列维护下凸壳即可。

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #define MAX_N 1000005
     5 #define INF 1000000000
     6 
     7 using namespace std;
     8 
     9 int n;
    10 int q[MAX_N];
    11 long long x[MAX_N];
    12 long long p[MAX_N];
    13 long long c[MAX_N];
    14 long long s[MAX_N];
    15 long long dp[MAX_N];
    16 
    17 void read()
    18 {
    19     cin>>n;
    20     memset(s,0,sizeof(s));
    21     memset(p,0,sizeof(p));
    22     for(int i=1;i<=n;i++)
    23     {
    24         cin>>x[i]>>p[i]>>c[i];
    25         s[i]=s[i-1]+x[i]*p[i];
    26         p[i]+=p[i-1];
    27     }
    28 }
    29 
    30 inline double slope(int i,int j)
    31 {
    32     return (double)(dp[i]+s[i]-dp[j]-s[j])/(p[i]-p[j]);
    33 }
    34 
    35 void work()
    36 {
    37     int l=1,r=1;
    38     q[1]=0,dp[0]=0;
    39     for(int i=1;i<=n;i++)
    40     {
    41         while(l<r && slope(q[l],q[l+1])<=x[i]) l++;
    42         dp[i]=dp[q[l]]+x[i]*(p[i]-p[q[l]])-s[i]+s[q[l]]+c[i];
    43         while(l<r && slope(q[r],i)<slope(q[r-1],q[r])) r--;
    44         q[++r]=i;
    45     }
    46     cout<<dp[n]<<endl;
    47 }
    48 
    49 int main()
    50 {
    51     read();
    52     work();
    53 }
  • 相关阅读:
    Interview with BOA
    Java Main Differences between HashMap HashTable and ConcurrentHashMap
    Java Main Differences between Java and C++
    LeetCode 33. Search in Rotated Sorted Array
    LeetCode 154. Find Minimum in Rotated Sorted Array II
    LeetCode 153. Find Minimum in Rotated Sorted Array
    LeetCode 75. Sort Colors
    LeetCode 31. Next Permutation
    LeetCode 60. Permutation Sequence
    LeetCode 216. Combination Sum III
  • 原文地址:https://www.cnblogs.com/Leohh/p/8407247.html
Copyright © 2011-2022 走看看