BZOJ 1096 [ZJOI2007]倉庫建設 斜率優化dp

1096: [ZJOI2007]倉庫建設php

Time Limit: 20 Secios

Memory Limit: 256 MB優化

題目鏈接spa

http://www.lydsy.com/JudgeOnline/problem.php?id=1096code

Descriptionorm

L公司有N個工廠,由高到底分佈在一座山上。如圖所示,工廠1在山頂,工廠N在山腳。 因爲這座山處於高原內陸地區(乾燥少雨),L公司通常把產品直接堆放在露天,以節省費用。忽然有一天,L公司的總裁L先生接到氣象部門的電話,被告知三天以後將有一場暴雨,因而L先生決定緊急在某些工廠創建一些倉庫以避免產品被淋壞。因爲地形的不一樣,在不一樣工廠創建倉庫的費用多是不一樣的。第i個工廠目前已有成品Pi件,在第i個工廠位置創建倉庫的費用是Ci。對於沒有創建倉庫的工廠,其產品應被運往其餘的倉庫進行儲藏,而因爲L公司產品的對外銷售處設置在山腳的工廠N,故產品只能往山下運(即只能運往編號更大的工廠的倉庫),固然運送產品也是須要費用的,假設一件產品運送1個單位距離的費用是1。假設創建的倉庫容量都都是足夠大的,能夠容下全部的產品。你將獲得如下數據: 工廠i距離工廠1的距離Xi(其中X1=0);  工廠i目前已有成品數量Pi;  在工廠i創建倉庫的費用Ci; 請你幫助L公司尋找一個倉庫建設的方案,使得總的費用(建造費用+運輸費用)最小。blog

Inputip

第一行包含一個整數N,表示工廠的個數。接下來N行每行包含兩個整數Xi, Pi, Ci, 意義如題中所述。

Outputci

僅包含一個整數,爲能夠找到最優方案的費用。get

Sample Input

3
0 5 10
5 3 100
9 6 10

Sample Output

32

HINT

 

題意

 

題解

n^2的dp很顯然就推出來了

而後斜率優化DP就吼了……

代碼:

#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 1000100
#define mod 10007
#define eps 1e-9
int Num;
//const int inf=0x7fffffff;   //нчоч╢С
const int inf=0x3f3f3f3f;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
//**************************************************************************************

ll p[maxn],s[maxn],c[maxn];
ll h[maxn];
ll t,w;
ll f[maxn],q[maxn];
int n;
ll slope(int k,int j)
{
    return double(f[j]-f[k]+h[j]-h[k])/double(p[j]-p[k]);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
       scanf("%lld%lld%lld",&s[i],&p[i],&c[i]);
    for(int i=1;i<=n;i++)
    {
        h[i]=h[i-1]+s[i]*p[i];
        p[i]=p[i-1]+p[i];
    }
    for(int i=1;i<=n;i++)
    {
        while(t<w&&slope(q[t],q[t+1])<s[i])t++;
        int j = q[t];
        f[i]=f[j]+s[i]*(p[i]-p[j])-h[i]+h[j]+c[i];
        while(t<w&&slope(q[w-1],q[w])>slope(q[w],i))w--;
        q[++w]=i;
    }
    printf("%lld\n",f[n]);
}
相關文章
相關標籤/搜索