【NOIP2012】开车旅行
题目描述:
小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即 d[i, j] = |Hi-Hj|
旅行过程中,小 A 和小 B 轮流开车,第一天小 A 开车,之后每天轮换一次。他们计划选择一个城市 S 作为起点,一直向东行驶,并且最多行驶 X 公里就结束旅行。小 A 和小 B 的驾驶风格不同,小 B 总是沿着前进方向选择一个最近的城市作为目的地,而小 A 总是沿着前进方向选择第二近的城市作为目的地(注意:本题中如果当前城市到两个城市的距离相同,则认为离海拔低的那个城市更近)。如果其中任何一人无法按照自己的原则选择目的城市,或者到达目的地会使行驶的总距离超出 X 公里,他们就会结束旅行。
在启程之前,小 A 想知道两个问题:
1.对于一个给定的 X=X0,从哪一个城市出发,小 A 开车行驶的路程总数与小 B 行驶的路程总数的比值最小(如果小 B 的行驶路程为 0,此时的比值可视为无穷大,且两个无穷大视为相等)。如果从多个城市出发,小 A 开车行驶的路程总数与小 B 行驶的路程总数的比值都最小,则输出海拔最高的那个城市。
- 对任意给定的 X=Xi 和出发城市 Si,小 A 开车行驶的路程总数以及小 B 行驶的路程总数。
朴素算法:利用循环首先统计出一个地方可以到达的最短路径和次短路径,然后循环统计长度这样的话算法的复杂度会很高,前面会计算出很多后面没有用到的内容。
算法:首先将所有的城市的高度按照从小到大的顺序排列,然后从1-N枚举城市,其中由于只能跳到比它本身要大的数字所以每一次处理完这个城市后就将该城市弹出,由于经过了排序所以该城市的距离它最近的节点分别为它左右端的节点,所以首先看左边,因为左边的高度较低而在距离相同的情况下城市越高越远所以首先选择左边的第一和第二个节点(前提是存在) 然后根据题目描述放入右边的节点。注意要特殊处理右边的第二个节点因为如果右边的距离更小的话那么就可以选择右边的。然后用数组G来存储从i出发的 j 表示第 2^(j+1)的城市的编号 G[i][j] 然后因为要分别处理a开车和b开车的距离所以使用f[i][j][k]来表示他们分别开车的距离和G数组一一对应 i 表示出发的城市, j 表示从 i 出发第 2^(j+1)的城市位置, k表示到达城市的a开车的距离 和b开车的距离 用0 和 1 表示然后就可以通过倍增计算出两点之间不超过 X 的最大距离