旅行问题
题目描述
John 打算驾驶一辆汽车周游一个环形公路。
公路上总共有 n 个车站,每站都有若干升汽油(有的站可能油量为零),每升油可以让汽车行驶一千米。
John 必须从某个车站出发,一直按顺时针(或逆时针)方向走遍所有的车站,并回到起点。
在一开始的时候,汽车内油量为零,John 每到一个车站就把该站所有的油都带上(起点站亦是如此),行驶过程中不能出现没有油的情况。
任务:判断以每个车站为起点能否按条件成功周游一周。
思路 破环成链+前缀和+单调队列
对于环路,我们需要破环成链,即开两倍的数组,对前n个数字进行复制。
定义: \(d[i]\) 为当前点获得的油量 \(oil[i]\) + 到下一个点的距离 \(dist[i(i - 1)]\)。 \(s[i]=\sum_{j=1}^i d[j]\) 。
顺时针
对于顺时针,我们需要满足从 \(i\) 点开始,走到 \(i+n\) 点,油量始终大于等于0。
考虑从 \(i\) 点走向 \(i+1\) 点时的情况,即 \(d[i]=s[i]-s[i-1]=oil[i]-dist[i]\ge 0\)。
由此可以推出,走到 \(i+x_{(0\le x\le n)}\) 点时,需要满足 \(s[i+x]-s[i-1] \ge 0\)。
从而转化为,在区间 \([i,i+n]\) 内找到最小值,满足 \(\min\{s[i,i+n]\}\ge s[i-1]\)。寻找区间里最小值可以用滑动窗口来维护。
Note
此时 \(s[i]\) 需要与 \(s[i-1]\) 进行对比,因此需要先将 \(s[i]\) 放入单调队列后,再进行答案的维护。
逆时针
对于逆时针,我们需要满足从 \(i+n\) 点开始,走到 \(i\) 点,油量始终大于等于0。
此时的 \(d[i]=oil[i]-dist[i-1]\)。考虑从 \(i\) 点走向 \(i-1\) 点时的情况,即 \(d[i]=s[i]-s[i-1]=oil[i]-dist[i-1]\ge 0\)
由此可以推出,走到 \(i-x_{(0\le x\le n)}\) 点时,需要满足 \(s[i]-s[i-x]\ge 0\)。
从而转化为,在区间 \([i-n,i]\) 内找到最大值,满足 \(\max\{s[i-n,i]\}\le s[i]\)。寻找区间里最大值可以用滑动窗口来维护。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
|