补充题目数据范围: 1 ≤ c ≤ 100 1\leq c \leq 100 1≤c≤100。
题解
首先读题,发现有图,有正边权,求最少花费,可以考虑用 dijkstra 求最短路来解决。
可是这道题既有点权(油价)又有边权,怎么解决呢?
在 DP 中,解决后效性的方法之一就是升维。同样,在这一题中,也可以通过升维的方式,表示出每一个状态。
考虑车有什么会变化的状态吗?很容易想到有 3 3 3 个状态:花费、所在城市、剩余油量,使用一个三元组 ( c o s t , c i t y , f u e l ) (cost,city,fuel) (cost,city,fuel) 表示。
如果跑 dijkstra 的话,需要一个状态作为小根堆排序依据,肯定是花费。
每到一个城市,车有两种选择:加 1 1 1 升油(加多升油可以转化为多次加一升油)、前往下一个城市。
-
加油:只有在当前车剩余油量 < < < 车容量时才可以加油(当然这里写不等于也是可以的,
想一想,为什么),可以从状态 ( c o s t , c i t y , f u e l ) (cost,city,fuel) (cost,city,fuel) 扩展到 ( c o s t + p [ c i t y ] , c i t y , f u e l + 1 ) (cost+p[city],city,fuel+1) (cost+p[city],city,fuel+1)。 -
前往下一个城市:这就是普通的 dijkstra 模板了,当边权 w w w 小于剩余油量时可以从状态 ( c o s t , c i t y , f u e l ) (cost,city,fuel) (cost,city,fuel) 扩展到 ( c o s t , n e x t _ c i t y , f u e l − w ) (cost,next\_city,fuel-w) (cost,next_city,fuel−w)。
然后这道题就结束了。
总的实现过程是:
-
使用优先队列 BFS(dijkstra),初始状态为 ( 0 , s , 0 ) (0,s,0) (0,s,0),放入优先队列中。
-
从队首取出队中 c o s t cost cost 最小的元素,考虑加 1 1 1 升油或前往下一个城市,并把可扩展到的状态放入队列。
-
不断重复第二步,直到取出的三元组 c i t y = e city=e city=e,这时的 c o s t cost cost 即为答案(因为 BFS 保证第一次取出的就是最优解)。