描述 Description
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 公司寻找一个仓库建设的方案,使得总的费用(建造费用 + 运输费用)最小。
输入格式 InputFormat
第一行包含一个整数 N,表示工厂的个数。接下来 N 行每行包含两个整数 Xi, Pi, Ci, 意义如题中所述。
输出格式 OutputFormat
仅包含一个整数,为可以找到最优方案的费用。
样例输入 SampleInput
3
0 5 10
5 3 100
9 6 10
样例输出 SampleOutput
32
斜率优化 DP。和 小 P 的牧场 那题一样的。。。
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define ll long long
const ll maxn=1000005;
ll i,j,t,n,m,l,r,k,z,y,x;
ll a[maxn],sum1[maxn],sum2[maxn],c[maxn],p[maxn];
ll f[maxn],q[maxn];
ll head,tail;
inline ll fracup(ll x,ll y)
{
return f[x]-f[y]+sum2[x]-sum2[y];
}
inline ll fracdown(ll x,ll y)
{
return sum1[x]-sum1[y];
}
int main()
{
scanf("%lld",&n);
sum1[0]=sum2[0]=0;
for (i=1;i<=n;i++) scanf("%lld%lld%lld",&a[i],&p[i],&c[i]),sum1[i]=sum1[i-1]+p[i],sum2[i]=sum2[i-1]+a[i]*p[i];
head=tail=0;q[tail]=0;
for (i=1;i<=n;i++)
{
while (tail>head && fracup(q[head+1],q[head])<a[i]*fracdown(q[head+1],q[head])) head++;
t=q[head];
f[i]=f[t]+a[i]*(sum1[i]-sum1[t])-sum2[i]+sum2[t]+c[i];
while (tail>head && fracup(q[tail],q[tail-1])*fracdown(i,q[tail])>fracup(i,q[tail])*fracdown(q[tail],q[tail-1])) tail--;
q[++tail]=i;
}
printf("%lld\n",f[n]);
return 0;
}