您的位置:首页 > 其它

[BZOJ1096] [ZJOI2007]仓库建设

2015-12-18 19:05 302 查看

传送门

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

题目大意

给定n个点间的距离,每个点的物品数和建仓库的花费,每个点的物品可以放在该点建的仓库或它后面点建的仓库,运输的费用为距离*物品数

题解

x[i]表示位置y[i]物品数量sumy[i]=∑ni=1y[i]sumxy=∑ni=1x[i]∗y[i]x[i]表示位置\\y[i]物品数量\\sumy[i]=\sum_{i=1}^ny[i]\\sumxy=\sum_{i=1}^nx[i]*y[i]

dp[i]=min{dp[j]+(sumy[i−1]−sumy[j])x[i]+(sumxy[j]−sumxy[i−1])+cost[i]}dp[i]=min\{dp[j]+(sumy[i-1]-sumy[j])x[i]+(sumxy[j]-sumxy[i-1])+cost[i]\}

dp[i]=min{dp[j]−sumy[j]x[i]+sumxy[j]}+sumy[i−1]x[i]−sumxy[i−1]+cost[i]dp[i]=min\{dp[j]-sumy[j]x[i]+sumxy[j]\}+sumy[i-1]x[i]-sumxy[i-1]+cost[i]

以上为O(n2)O(n^2)的朴素DP

然后我们来斜率优化下

当j<k时取k比取j更优j

dp[j]−sumy[j]x[i]+sumxy[j]<=dp[k]−sumy[k]x[i]+sumxy[k]dp[j]-sumy[j]x[i]+sumxy[j]<=dp[k]-sumy[k]x[i]+sumxy[k]

(dp[j]+sumxy[j])−(dp[k]+sumxy[k])sumy[j]−sumy[k]>=x[i]\frac{(dp[j]+sumxy[j])-(dp[k]+sumxy[k])}{sumy[j]-sumy[k]}>=x[i]

sumxy[],sumy[]都单调,单调队列维护sumxy[],sumy[]都单调,单调队列维护

O(n2)O(n^2)版本

const
maxn=1000005;
var
dp,x,y,sumy,sumxy,cost:array[0..maxn]of int64;
i,j,k:longint;
n:longint;
function min(a,b:int64):int64;
begin
if a<b then exit(a) else exit(b);
end;

begin
readln(n); sumy[0]:=0; sumxy[0]:=0;
for i:=1 to n do
begin
readln(x[i],y[i],cost[i]);
sumy[i]:=sumy[i-1]+y[i];
sumxy[i]:=sumxy[i-1]+x[i]*y[i];
end;
dp[1]:=cost[1];
for i:=1 to n do
begin
dp[i]:=maxlongint;
for j:=0 to i-1 do
dp[i]:=min(dp[i],dp[j]+(sumy[i-1]-sumy[j])*x[i]+(sumxy[j]-sumxy[i-1])+cost[i]);
end;
writeln(dp
);
end.


斜率优化版本

const
maxn=1000005;
var
dp,x,y,sumy,sumxy,cost:array[0..maxn]of int64;
t:array[0..maxn]of longint;
i,j,k:longint;
n,l,r,tt:longint;
function f(a,b:longint):int64;
var c:int64;
begin
c:=(dp[a]+sumxy[a]-dp[b]-sumxy[b]);
exit(c);
end;

begin
readln(n); sumy[0]:=0; sumxy[0]:=0;
for i:=1 to n do
begin
readln(x[i],y[i],cost[i]);
sumy[i]:=sumy[i-1]+y[i];
sumxy[i]:=sumxy[i-1]+x[i]*y[i];
dp[i]:=sumy[i-1]*x[i]-sumxy[i-1]+cost[i];
end;
t[1]:=0; l:=1; r:=1;
for i:=1 to n do
begin
while (l<r)and(f(t[l],t[l+1])>=x[i]*(sumy[t[l]]-sumy[t[l+1]])) do inc(l);
tt:=t[l];
dp[i]:=dp[i]+dp[tt]-sumy[tt]*x[i]+sumxy[tt];
while (l<r)and(f(t[r-1],t[r])*(sumy[t[r]]-sumy[i])>f(t[r],i)*(sumy[t[r-1]]-sumy[t[r]])) do dec(r);
inc(r); t[r]:=i;
end;
writeln(dp
);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: