P1772 [ZJOI2006] 物流运输
Description
一批货物从码头 A 运到码头 B。需要
n
n
n 天才能运完,要转停好几个码头。
若某个码头会关闭,必须修改运输路线并带来损耗。要求订一个
n
n
n 天的运输计划,最小化总成本。
n n n 表示货物运输所需天数, m m m 表示码头数, k k k 表示每次修改路线成本, e e e 表示航线条数。
e e e 条双向航线描述:航线连接两个码头编号、航线费用。其中码头 A 编号为 1 1 1,码头 B 编号为 m m m。
d d d 个不可用码头时间: p , a , b p,a,b p,a,b。表示编号为 p p p 的码头在 [ a , b ] [a,b] [a,b] 天之内无法装卸货物。同一个码头有可能在多个时间段内不可用。保证任何时间存在从码头 A 到码头 B 的运输路线。
总成本为
n
n
n 天运输路线长度之和
+
k
×
+ k \times
+k× 改变路线的次数。
求最小总成本。
对于
100
%
100\%
100% 的数据,
1
≤
n
≤
100
1 \le n \le 100
1≤n≤100,
1
≤
m
≤
20
1\le m \le 20
1≤m≤20,
1
≤
k
≤
500
1 \le k \le 500
1≤k≤500,
1
≤
e
≤
200
1 \le e \le 200
1≤e≤200。
Solution
Pre:
这题初见看到
m
≤
20
m\le 20
m≤20 ,想了想感觉是状压路径(除掉共同终点
m
m
m 有
2
m
−
1
2^{m-1}
2m−1 条),然后按天数转移,最后写完
b
f
s
+
bfs+
bfs+状压线性DP 偷了
10
p
t
s
10pts
10pts, 好像是
b
f
s
bfs
bfs 写炸导致队列
M
L
E
MLE
MLE。最后死都没调出来不想调。
倒是你谷还是有神犇写了
d
f
s
+
dfs+
dfs+状压线性DP 暴力AC,我也算这个做法颅内AC了(第一次过是Copy这位的标程,把自己的代码放在地下注释掉后提交的qwq…)
Now:
题后参考了题解:
n
2
n^2
n2 处理
n
l
o
g
n
+
m
nlogn+m
nlogn+m 的最短路——求出第
i
i
i 到
j
j
j 天的最短路
c
[
i
]
[
j
]
c[i][j]
c[i][j](
i
∼
j
i\sim j
i∼j只走同一路线的最小花费)
DP状态:
f
[
i
]
f[i]
f[i] 为前
i
i
i 天最优方案
状态转移:
f
[
i
]
=
m
i
n
(
f
[
j
−
1
]
+
c
[
j
]
[
i
]
∗
(
i
−
j
+
1
)
+
k
)
,
j
∈
[
1
,
i
]
f[i]=min(f[j-1]+c[j][i]*(i-j+1)+k), j\in[1,i]
f[i]=min(f[j−1]+c[j][i]∗(i−j+1)+k),j∈[1,i]
特别地:由于第
0
0
0 天到 第
1
1
1 天“切换路线”无意义,所以使
f
[
0
]
=
−
k
f[0]=-k
f[0]=−k(抵消无效转移成本
k
k
k )。
题外话:本题按天数转移的方程类似于 UVA11400 照明系统设计 Lighting System Design ,本蒟蒻当天才写完对着紫书贺思路qwq
Code
d=read();
for(ll i = 1; i <= d ; i++){
ll p=read(), l=read(), r=read();
for(ll j = l ; j <= r ; j++) un[j][p]=1;//第j天第p码头不可行
}
memset(f, 0x3f, sizeof(f));
f[0]=-k;//特别的
for(ll i = 1; i <= n ; i++){
memset(non, 0, sizeof(non));//区间时间内的不可达码头
for(ll j = i; j > 0 ; j--){//从第i天向第j天反着推
for(ll p = 1; p <= m ; p++)//每天更新当天不可用码头即可(小优化)
if(un[j][p]) non[p]=1;
ll nw=Dijkstra();
if(nw>=1e16) break;
f[i]=min(f[i], f[j-1]+(i-j+1)*nw+k);
}
}