问题描述
8 月P 教授要去看奥运,但是他割舍不下自己的一大堆智力玩具。于是,他决定把所有玩具都运到北京去。P教授使用自己的物体维数压缩器ODZ(Object Dimension Zipper)来给玩具装箱。ODZ可以将任意物品变成一维,再装到一种特殊的一维容器中。P 教授有编号为1…N的N件玩具,第i 件玩具经过ODZ处理后一维长度是Ci。为了方便整理,P 教授要求在一个一维容器中的玩具编号是连续的。同时,如果一个一维容器中有多个玩具,那么相信两件玩具之间要加入1 个单位长度的填充物。形式地说,如果将第i 到第j 件玩具放在一个容器中 ( i < j ),那容器的长度将为
x=j−i+∑jk=iCk
制作容器的费用与容器长度有关。根据P 教授的研究,如果容器长度为x,其制作费用为(x-L)^2,期中L 是一个常量。P 教授不关心容器的数目,他可以制造出任意长度的容器(甚至超过L),但他希望费用最小。
数据输入
第一行输入两个整数N和L,接下来N行输入Ci。1<=N<=50000,1<=L、Ci<=10^7。
数据输出
输出最小费用。
样例输入
5 4
3
4
2
1
4
样例输出
1
题解:
sum[i] 表示
s
i
g
m
a
(
k
=
1
−
>
i
)
c
[
k
]
sigma( k = 1->i)c[k]
sigma(k=1−>i)c[k]
d
p
[
i
]
=
m
i
n
(
d
p
[
j
]
+
(
s
u
m
[
i
]
−
s
u
m
[
j
]
+
i
−
j
−
1
−
L
)
2
)
(
j
<
i
)
dp[i]=min(dp[j]+(sum[i]-sum[j]+i-j-1-L)^2) (j < i)
dp[i]=min(dp[j]+(sum[i]−sum[j]+i−j−1−L)2)(j<i)
令
f
[
i
]
=
s
u
m
[
i
]
+
i
,
c
=
1
+
L
f[i]=sum[i]+i,c=1+L
f[i]=sum[i]+i,c=1+L
则
d
p
[
i
]
=
m
i
n
(
d
p
[
j
]
+
(
f
[
i
]
−
f
[
j
]
−
c
)
2
)
dp[i]=min(dp[j]+(f[i]-f[j]-c)^2)
dp[i]=min(dp[j]+(f[i]−f[j]−c)2)
1.证明决策单调性
假设在状态i处的k决策优于j决策,即
d
p
[
k
]
+
(
f
[
i
]
−
f
[
k
]
−
c
)
2
<
=
d
p
[
j
]
+
(
f
[
i
]
−
f
[
j
]
−
c
)
2
dp[k]+(f[i]-f[k]-c)^2<=dp[j]+(f[i]-f[j]-c)^2
dp[k]+(f[i]−f[k]−c)2<=dp[j]+(f[i]−f[j]−c)2
则对于i后的所有状态t,要证明决策单调性
即
d
p
[
k
]
+
(
f
[
t
]
−
f
[
k
]
−
c
)
2
<
=
d
p
[
j
]
+
(
f
[
t
]
−
f
[
j
]
−
c
)
2
dp[k]+(f[t]-f[k]-c)^2<=dp[j]+(f[t]-f[j]-c)^2
dp[k]+(f[t]−f[k]−c)2<=dp[j]+(f[t]−f[j]−c)2
只要证
d
p
[
k
]
+
(
f
[
i
]
+
v
−
f
[
k
]
−
c
)
2
<
=
d
p
[
j
]
+
(
f
[
i
]
+
v
−
f
[
j
]
−
c
)
2
dp[k]+(f[i]+v-f[k]-c)^2<=dp[j]+(f[i]+v-f[j]-c)^2
dp[k]+(f[i]+v−f[k]−c)2<=dp[j]+(f[i]+v−f[j]−c)2
只要证
d
p
[
k
]
+
(
f
[
i
]
−
f
[
k
]
−
c
)
2
+
2
∗
v
∗
(
f
[
i
]
−
f
[
k
]
−
c
)
+
v
2
<
=
d
p
[
j
]
+
(
f
[
i
]
−
f
[
j
]
−
c
)
2
+
2
∗
v
∗
(
f
[
i
]
−
f
[
j
]
−
c
)
+
v
2
dp[k]+(f[i]-f[k]-c)^2+2 * v * (f[i]-f[k]-c)+v^2<=dp[j]+(f[i]-f[j]-c)^2+2 * v * (f[i]-f[j]-c)+v^2
dp[k]+(f[i]−f[k]−c)2+2∗v∗(f[i]−f[k]−c)+v2<=dp[j]+(f[i]−f[j]−c)2+2∗v∗(f[i]−f[j]−c)+v2
只要证
2
∗
v
∗
(
f
[
i
]
−
f
[
k
]
−
c
)
<
=
2
∗
v
∗
(
f
[
i
]
−
f
[
j
]
−
c
)
2 * v * (f[i]-f[k]-c)<=2* v * (f[i]-f[j]-c)
2∗v∗(f[i]−f[k]−c)<=2∗v∗(f[i]−f[j]−c)
即
f
[
k
]
>
=
f
[
j
]
f[k]>=f[j]
f[k]>=f[j](显然)
证明完毕
2.求斜率方程
因为
d
p
[
k
]
+
(
f
[
i
]
−
f
[
k
]
−
c
)
2
<
=
d
p
[
j
]
+
(
f
[
i
]
−
f
[
j
]
−
c
)
2
dp[k]+(f[i]-f[k]-c)^2<=dp[j]+(f[i]-f[j]-c)^2
dp[k]+(f[i]−f[k]−c)2<=dp[j]+(f[i]−f[j]−c)2
展开
d
p
[
k
]
+
f
[
i
]
2
−
2
∗
f
[
i
]
∗
(
f
[
k
]
+
c
)
+
(
f
[
k
]
+
c
)
2
<
=
d
p
[
j
]
+
f
[
i
]
2
−
2
∗
f
[
i
]
∗
(
f
[
j
]
+
c
)
+
(
f
[
j
]
+
c
)
2
dp[k]+f[i]^2-2 * f[i] * (f[k]+c)+(f[k]+c)^2 <=dp[j]+f[i]^2-2 * f[i] *(f[j]+c)+(f[j]+c)^2
dp[k]+f[i]2−2∗f[i]∗(f[k]+c)+(f[k]+c)2<=dp[j]+f[i]2−2∗f[i]∗(f[j]+c)+(f[j]+c)2
即
d
p
[
k
]
−
2
∗
f
[
i
]
∗
(
f
[
k
]
+
c
)
+
(
f
[
k
]
+
c
)
2
<
=
d
p
[
j
]
−
2
∗
f
[
i
]
∗
(
f
[
j
]
+
c
)
+
(
f
[
j
]
+
c
)
2
dp[k]-2 * f[i] * (f[k]+c)+(f[k]+c)^2<=dp[j]-2 * f[i] * (f[j]+c)+(f[j]+c)^2
dp[k]−2∗f[i]∗(f[k]+c)+(f[k]+c)2<=dp[j]−2∗f[i]∗(f[j]+c)+(f[j]+c)2
即
(
d
p
[
k
]
+
(
f
[
k
]
+
c
)
2
−
d
p
[
j
]
−
(
f
[
j
]
+
c
)
2
)
/
2
∗
(
f
[
k
]
−
f
[
j
]
)
<
=
f
[
i
]
(dp[k]+(f[k]+c)^2 -dp[j]-(f[j]+c)^2)/2 * (f[k]-f[j])<=f[i]
(dp[k]+(f[k]+c)2−dp[j]−(f[j]+c)2)/2∗(f[k]−f[j])<=f[i]
f[i]是单调递增的,我们使用队列维护一个下凸壳,每次取出队头作为决策 , 加入决策i时,令队尾为q[r],前一个为q[r-1] 满足斜率(q[r],i)<斜率(q[r-1],q[r])时,显然队尾是无效的,将其弹出
(题解来自hzwer http://hzwer.com/2114.html )
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#define LiangJiaJun main
#define INF 1999122700000000LL
using namespace std;
long long f[50004];
int n,L;
long long c[50004],a[50004];
long long q[50004];
long long SQR(long long m){return m * m ;}
double slop(int j,int k){
return (f[k]-f[j]+SQR(a[k]+L)-SQR(a[j]+L))/(2.0*(a[k]-a[j]));
}
int t,w;
int LiangJiaJun (){
for(int i=0;i<=50001;i++)f[i]=INF;
f[0]=0;
scanf("%d%d",&n,&L);
a[0]=0;++L;
for(int i=1;i<=n;i++){
scanf("%lld",&c[i]);
a[i]=a[i-1]+c[i];
}
for(int i=1;i<=n;i++)a[i]+=(long long)i;
t=w=1;q[w]=0;
for(int i=1;i<=n;i++){
while(t<w && slop(q[t],q[t+1]) <= a[i]) ++t;
int last = q[t];
f[i]=f[last]+SQR(a[i]-a[last]-L);
while(t<w && slop(q[w],i) <= slop(q[w-1],q[w])) w--;
q[++w]=i;
}
cout<<f[n]<<endl;
return 0;
}