Powered by:NEFU AB-IN
Link
文章目录
2019.拖拉机
-
题意
-
思路
问从起点到终点需要最少移开多少障碍物,其实也就等价于最少经过多少障碍物,那么就可以转化为图论的最短路问题,两者等价性成立(原问题的每个方案与起点到终点的路径相互对应)
- 点:格子
- 边:上下左右四联通
- 边权:此题为点权
- 如果为障碍物,权值为1
- 如果为空地,权值为0
问题转化为了边权只有0或1的最短路问题
- 边权只有0或1的最短路问题:双端队列广搜
- 如果边权为0的话,将此点加到队头
- 如果边权为1的话,将此点加到队尾
- 拓展时每个点,出队只出一次,入队可入多次
- 本质为简化版的dijkstra算法
- 因边权只有0和1,把堆换成了双端队列
- 性质:在任何时刻,在双端队列的所有距离都是升序,所以第一个值一定是最小值,可以起到堆的作用
- 时间复杂度线性
- 边权只有1的最短路问题:广搜
-
代码
''' Author: NEFU AB-IN Date: 2022-01-28 13:00:59 FilePath: \ACM\Acwing\2019.py LastEditTime: 2022-01-29 13:34:54 ''' from collections import deque N = 1010 INF = int(2e9) g = [[0 for _ in range(N)] for _ in range(N)] dist = [[INF for _ in range(N)] for _ in range(N)] st = [[0 for _ in range(N)] for _ in range(N)] dx = [-1, 0, 1, 0] dy = [0, 1, 0, -1] #上右下左 def bfs(sx, sy): q = deque() q.appendleft([sx, sy]) dist[sx][sy] = 0 while len(q): t = q.pop() if st[t[0]][t[1]]: #出队去重 continue st[t[0]][t[1]] = 1 if t[0] == 0 and t[1] == 0: #起点已经走完了 break for i in range(4): x = t[0] + dx[i] y = t[1] + dy[i] if x >= 0 and x < N and y >= 0 and y < N: w = 0 if g[x][y]: w = 1 if dist[x][y] > dist[t[0]][t[1]] + w: dist[x][y] = dist[t[0]][t[1]] + w if w == 0: q.append([x, y]) #加到队头 else: q.appendleft([x, y]) #加到队尾 return dist[0][0] if __name__ == "__main__": n, sx, sy = map(int, input().split()) for _ in range(n): x, y = map(int, input().split()) # 障碍为1 g[x][y] = 1 print(bfs(sx, sy))