题目
http://poj.org/problem?id=1180
解题思路
n
2
n^2
n2的
d
p
:
dp:
dp:
f
[
i
]
=
m
i
n
(
f
[
j
]
+
s
u
m
T
[
i
]
∗
(
s
u
m
C
[
i
]
−
s
u
m
C
[
j
]
)
+
S
∗
(
s
u
m
C
[
N
]
−
s
u
m
C
[
j
]
)
)
f[i]=min(f[j]+sumT[i]*(sumC[i]-sumC[j])+S*(sumC[N]-sumC[j]))
f[i]=min(f[j]+sumT[i]∗(sumC[i]−sumC[j])+S∗(sumC[N]−sumC[j]))
f
[
j
]
=
(
S
+
s
u
m
T
[
i
]
)
∗
s
u
m
C
[
j
]
+
f
[
i
]
−
s
u
m
T
[
i
]
∗
s
u
m
C
[
i
]
−
S
∗
s
u
m
C
[
n
]
f[j]=(S+sumT[i])*sumC[j]+f[i]-sumT[i]*sumC[i]-S*sumC[n]
f[j]=(S+sumT[i])∗sumC[j]+f[i]−sumT[i]∗sumC[i]−S∗sumC[n]
每个待求解的状态
f
[
i
]
f[i]
f[i]都对应着一条直线的截距,直线的斜率是
S
+
s
u
m
T
[
i
]
S+sumT[i]
S+sumT[i],截距未知。当截距最小化,
f
[
i
]
f[i]
f[i]也取到最小值。
有三个决策点
j
1
,
j
2
,
j
3
(
j
1
<
j
2
<
j
3
)
j1,j2,j3(j1<j2<j3)
j1,j2,j3(j1<j2<j3)
j
2
j2
j2有可能成为最优决策,当且仅当
f
[
j
2
]
−
f
[
j
1
]
s
u
m
C
[
j
2
]
−
s
u
m
C
[
j
1
]
<
f
[
j
3
]
−
f
[
j
2
]
s
u
m
C
[
j
3
]
−
s
u
m
C
[
j
2
]
\frac{f[j2]-f[j1]}{sumC[j2]-sumC[j1]}<\frac{f[j3]-f[j2]}{sumC[j3]-sumC[j2]}
sumC[j2]−sumC[j1]f[j2]−f[j1]<sumC[j3]−sumC[j2]f[j3]−f[j2]
用单调队列维护
“
下
凸
壳
”
“下凸壳”
“下凸壳”
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,s,t,c,sumt[10001],sumc[10001],f[10001],q[10001];
int main(){
scanf("%d%d",&n,&s);
for(int i=1;i<=n;i++) scanf("%d%d",&t,&c),sumt[i]=sumt[i-1]+t,sumc[i]=sumc[i-1]+c;
memset(f,0x3f,sizeof(f));
int l=1,r=1; q[1]=0; f[0]=0;
for(int i=1;i<=n;i++){
while(l<r&&(f[q[l+1]]-f[q[l]])<=(s+sumt[i])*(sumc[q[l+1]]-sumc[q[l]])) l++;
f[i]=f[q[l]]-(s+sumt[i])*sumc[q[l]]+sumt[i]*sumc[i]+s*sumc[n];
while(l<r&&(f[q[r]]-f[q[r-1]])*(sumc[i]-sumc[q[r]])>=(f[i]-f[q[r]])*(sumc[q[r]]-sumc[q[r-1]])) r--;
q[++r]=i;
}
printf("%d",f[n]);
}