您的位置:首页 > 编程语言 > PHP开发

[斜率优化的dp]storage题解

2012-10-15 14:54 190 查看
[题目描述]

L公司有N个工厂,由高到底分布在一座山上。工厂1在山顶,工厂N在山脚。

     由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用。突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先生决定紧急在某些工厂建立一些仓库以免产品被淋坏。
    由于地形的不同,在不同工厂建立仓库的费用可能是不同的。第i个工厂目前已有成品Pi件,在第i个工厂位置建立仓库的费用是Ci。对于没有建立仓库的工厂,其产品应被运往其他的仓库进行储藏,而由于L公司产品的对外销售处设置在山脚的工厂N,故产品只能往山下运(即只能运往编号更大的工厂的仓库),当然运送产品也是需要费用的,假设一件产品运送1个单位距离的费用是1。假设建立的仓库容量都都是足够大的,可以容下所有的产品。

    你将得到以下数据:

1. 工厂i距离工厂1的距离Xi(其中X1=0);

2. 工厂i目前已有成品数量Pi;

3. 在工厂i建立仓库的费用 Ci;

[题解]
      这道题很坑爹,裸的dp方程都让我推了好久.

      显然,f[i]=c[i]+min(f[j]+sigma(p[k]*d[k]))(k>j且k<=i)(为了接下来运算的方便,将i也包括进来)(d[i],即为题目中的xi,为了不与下面的x重复,用d代替)

      令s1[i]=sigma(p[k]x[k]),k<=i;s2=sigma(p[k]),k<=i

      f[i]=min(f[j]+x[i]*(s2[i]-s2[j])-(s1[i]-s1[j]))+c[i]

      经过一系列转化,我们得到:f[i]=min(f[j]+s1[j]-d[i]s2[j])+d[i]s2[i]-s1[i]+c[i].

      到这里,剩下的就很简单了.我Wa了若干次,原因一个是因为单调性搞错,导致凸壳的方向搞错,另一个是因为没有将f[0]加入单调队列(坑爹啊),最后一个是因为将除法移项时没注意移的项的正负性而没有变号.

Code

program storage;
type int=int64;real=extended;
var
i,j:longint;
l,r,n:longint;
d,p,c,x,y,s1,s2,f:array[0..1000000]of real;
k,a,b:real;
begin
assign(input,'storage.in');reset(input);
assign(output,'storage.out');rewrite(output);
read(n);s1[0]:=0;s2[0]:=0;
for i:=1 to n do begin
read(d[i],p[i],c[i]);
s1[i]:=s1[i-1]+p[i]*d[i];
s2[i]:=s2[i-1]+p[i];
end;
l:=1;r:=1;f[0]:=0;x[0]:=0;y[0]:=0;
for i:=1 to n do begin
while(l<r)and((y[l]-y[l+1])>(x[l]-x[l+1])*d[i])do inc(l);
f[i]:=c[i]-s1[i]+d[i]*s2[i]+y[l]-d[i]*x[l];
a:=s2[i];b:=f[i]+s1[i];
while(l<r)and((y[r]-y[r-1])*(a-x[r])>(x[r]-x[r-1])*(b-y[r]))do dec(r);
inc(r);x[r]:=a;y[r]:=b;
end;
write(f
:0:0);
close(input);close(output);
end.


BY QW
转载请注明出处
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息