我的第一场Div1,感觉很有挑战性,也很有趣,而且计分还是很宽容的.
983A Finite or not?
983B XOR-pyramid
983C Elevator
题意
一栋9层的大楼,有一座最多容纳4个人的电梯,现在有n(2000)个人在不同的层排队,每个人有当前所在层及要到达的层,要求必须按顺序进入电梯(即使层数不同也如此),但是出电梯的顺序无所谓,电梯移动一层耗时1,一个人进或出耗时1,问如何安排电梯行程使得耗时最少,求最短耗时.
分析
2000个人,9层大楼,4人电梯,求最优值,数字都比较小,考虑dp.
预处理:一个人只会进出各一次,所以进出耗时可以不在过程中计算,最后答案直接加n*2
dp类型:此类题会出现极多的空状态,所以使用记忆化搜索的方式.
状态表示:dp[i][j]表示接到第i个人后,当前电梯内人的去向为j时到过程结束的最小耗时.
每个人的去向是一个0到9之内的整数,其中0表示没有这个人,4次组合起来就是j,即0到9999.
边界条件:dp[n][j]=search(from[n],j);
意思是现在在from[n]层,要将电梯内的人送到j[0],j[1],j[2],j[3]层中.
可以只看最高层和最低层up,down,即
min(|from[n]−down|,|from[n]−up|)+|up−down|
m
i
n
(
|
f
r
o
m
[
n
]
−
d
o
w
n
|
,
|
f
r
o
m
[
n
]
−
u
p
|
)
+
|
u
p
−
d
o
w
n
|
然后从from[n]开始先到最高层再到最低层,或者先到最低层再到最高层,取一个较小值.
答案表示:ans=dp[1][to[1]]+from[1]+n*2,从接到第一个人开始dp
状态转移:注意电梯的层数,dp[i][j]转移到dp[i+1][j’]时,所用时间实际上是电梯层数从from[i]到j的某几个值,再到from[i+1]的时间.选择j中的值时,实际上可以只选上下界up,down,然后耗时为search(from[i],from[i+1],down,up),即
min(|fi−down|+|fi+1−up|,|fi−up|+|fi+1−down|)+up−down
m
i
n
(
|
f
i
−
d
o
w
n
|
+
|
f
i
+
1
−
u
p
|
,
|
f
i
−
u
p
|
+
|
f
i
+
1
−
d
o
w
n
|
)
+
u
p
−
d
o
w
n