D. 帮帮小叮当 2014新生暑假个人排位赛07
题目描述
小叮当刚刚学会了传送门的使用方法,可是它不小心跌落到二维空间一个 n * m 的矩阵格子世界的入口(1,1)处,
他得知出口在(n,m)处,每穿越一个格子门,它的体力值会下降。
又饿又累的他 IQ 已经降为负数了,聪明的你,能帮他规划一下路线,使得它体力值下降的最少吗?
每一行有且仅有一个传送门,但是小叮当上课睡着了,只学会了用传送门瞬移到相邻行的另一个传送门且耗 1 滴体力。
此外,他就只能通过格子门走到相邻四个格子中的一个,也耗 1 滴体力。
ps,由于符合的路径太多了,你只需要告诉我们体力值消耗最小值。
输入格式
每组数据,第一行给 n,m 两个整数(2 <= n,m <= 10000),接下来一行,有 n 个数字,代表该行传送门的位置 x( 1 <= x <= m )。以 n,m 都为0结束。Mays温馨提醒:数据组数略大于100。
输出格式
对每组输入,输出一行,体力消耗最小值。
输入样例
5 5
5 4 3 2 1
0 0
输出样例
8
赛后AC:Y
题目大意:
给出一个n*m的矩阵,每一行有一个传送门,走到传送门时可以耗费一个花费
跳到相邻行(注意可上可下)的传送门上。此外,如果只是朴素的上下左右移动那么耗费都是一
要求从(1,1)到(n,m)的最小花费
思路&反省:
(1)首先想到的是类似于贪心的方法
因为不管是直接移动还是传送,只看y方向的话,花费都是一
所以在竖直方向上不管纯采用传送还是纯朴素移动还是都有,从总花费上看没有区分
所以就想到了只要看看到起点最近的那个传送门的水平距离和到终点最近的那个
传送门的水平距离是否小于水平朴素距离就好了
但是这是错的,因为用传送门的话是可能出现向下移动再向上移动的情况
这么一来竖直方向上的移动就一定等于m了
正确的方法应该是使用对短路算法,一共建立n+n+n-1+n-1条边
分别是起点到每一个传送门的边,每一个传送门到终点的边,
和相邻传送门间的双向边(这个是坑,本以为不会往回走的,结果WA了,加了双向之后就A了)
但是这道题还会卡一卡dijstra的常数倍时间,应该用SPFA做,才可以不T
这里还复习了一次静态临接表的手写法,以后还是尽量用手写的吧,弃用vector
代码里的注释都写得很清楚了,看吧
下面是AC代码