广度优先搜索-鸣人和佐助

鸣人和佐助:佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢?
已知一张地图(以二维矩阵的形式表示)以及佐助和
鸣人的位置。地图上的每个位置都可以走到,只不过有些位置上有
大蛇丸的手下(#),需要先打败大蛇丸的手下才能到这些位置。

鸣人有一定数量的查克拉,每一个单位的查克拉可以打败一
个大蛇丸的手下。假设鸣人可以往上下左右四个方向移动,
每移动一个距离需要花费1个单位时间,打败大蛇丸的手下
不需要时间。如果鸣人查克拉消耗完了,则只可以走到没有
大蛇丸手下的位置,不可以再移动到有大蛇丸手下的位置。
佐助在此期间不移动,大蛇丸的手下也不移动。请问,鸣人
要追上佐助最少需要花费多少时间?
输入:输入的第一行包含三个整数:M,N,T。代表M行N列的地图和
鸣人初始的查克拉数量T。0 < M,N < 200,0 ≤ T < 10
后面是M行N列的地图,其中@代表鸣人,+代表佐助。*代表通路,#代表大蛇丸的手下。
输出:输出包含一个整数R,代表鸣人追上佐助最少需要花费的时间。
如果鸣人无法追上佐助,则输出-1。
样例输入1
4 4 1
#@##
**##
###+
****
样例输出1
6

样例输入2
4 4 2
#@##
**##
###+
****
样例输出2
4

一个经典的错误样例;
3 6 1
@#**** 
*#*###
***##+
正确答案应该是11;
但是如果利用二维标记答案是-1;因为二维标记是bfs找最短路,
当(1,1)——>(2,1)——>(3,1)——>(3,2)——>(3,3)——>(2,3)——>(1,3),
当这样找到(1,3)时,(1,3)早已经被(1,1)——>(1,2)——>(1,3)
走过并标记了,所以这条不需要查克拉的路就走不下去了,输出-1;
用三维数组就可以避免这种情况;比如刚才走到(1,3)这个点,区分有0、1查克拉的情况
visited[1][3][0] = 1,走到该点(1,3),用了1个,目前查克拉数量是0
visited[1][3][1] = 1,走到该点(1,3),没有用过1查克拉,目前查克拉数量是1,
这样就可以描述通过不同路径走到该点,拥有查克拉的数量的三维数组来描述状态,
都是到达(1,3)这个点,但是查克拉的数量不一致,所以就是新的一种状态,这样就不与
之前的路产生冲突了。

思路:这道题的状态是什么?是又鸣人的所在位置以及鸣人所剩查克拉决定的,(i,j,n),
初始状态是(i0,j0,N),终止状态是(i,i,n),达到佐助位置即可。
因为用广搜,所以到达即是最短。用广搜的话就要加入查克拉的消耗情况,
所以是三维的visit数组。
这题与以往不一样的地方在于该点走过后,还是可以再访问的,因为多了一个查克拉的值。

https://blog.csdn.net/WaveBridge/article/details/74993874

python代码:
  1 import queue
  2 
  3 # 地图
  4 maps = []
  5 # 分别代表鸣人和佐助的位置
  6 r1, c1, r2, c2 = 0, 0, 0, 0
  7 # 访问标记
  8 visited = []
  9 # 四个方向数组
 10 direction = [[1, 0], [-1, 0], [0, 1], [0, -1]]
 11 
 12 
 13 class Node:
 14     # 所在位置
 15     r = 0
 16     c = 0
 17     # 查克拉剩余
 18     t = 0
 19     # 所在层数,路径长度
 20     level = 0
 21 
 22     def __init__(self, rr, cc, tt, level1):
 23         self.r = rr
 24         self.c = cc
 25         self.t = tt
 26         self.level = level1
 27 
 28 
 29 # 获取鸣人和佐助的r,c
 30 def getTwoDimensionListIndex(list_map, value):
 31     r, c = 0, 0
 32     for i in range(len(list_map)):
 33         for j in range(len(list_map[i])):
 34             if list_map[i][j] == value:
 35                 r = i
 36                 c = j
 37                 break
 38     return r, c
 39 
 40 
 41 def bfs(r, c, k):
 42     global maps, r1, c1, r2, c2, visited
 43     new_node = Node(r1, c1, k, 0)
 44     q = queue.Queue()
 45     q.put(new_node)
 46     while not q.empty():
 47         temp = q.get()
 48         # 找到佐助
 49         if temp.r == r2 and temp.c == c2:
 50             cost_time = temp.level
 51             return cost_time
 52         # 把当前节点四个方向的节点入队
 53         for i in range(4):
 54             temp2 = Node(0, 0, 0, 0)
 55             temp2.r = temp.r + direction[i][0]
 56             temp2.c = temp.c + direction[i][1]
 57             # 保证访问的点不越界
 58             if 0 <= temp2.r < r and 0 <= temp2.c < c:
 59                 # 若为"#"并且查克拉够 并且没访问过 可访问
 60                 if maps[temp2.r][temp2.c] == "#" and temp.t >= 1 and visited[temp2.r][temp2.c][temp.t-1] == 0:
 61                     temp2.t = temp.t - 1
 62                     temp2.level = temp.level + 1
 63                     q.put(temp2)
 64                     visited[temp2.r][temp2.c][temp2.t] = 1
 65                 # 不是# 并且未访问过
 66                 elif maps[temp2.r][temp2.c] != "#" and visited[temp2.r][temp2.c][temp.t] == 0:
 67                     temp2.t = temp.t
 68                     temp2.level = temp.level + 1
 69                     q.put(temp2)
 70                     visited[temp2.r][temp2.c][temp2.t] = 1
 71     return 0
 72 
 73 
 74 def main():
 75     global maps, r1, c1, r2, c2, visited
 76     # k-查克拉的数量
 77     r, c, k = map(int, input().split())
 78 
 79     for i in range(r):
 80         temp = list(input())
 81         maps.append(temp)
 82     # [['#', '@', '#', '#'],['*', '*', '#', '#'],
 83     #  ['#', '#', '#', '+'],['*', '*', '*', '*']]
 84     # 查找鸣人和佐助的位置
 85     r1, c1 = getTwoDimensionListIndex(maps, "@")
 86     r2, c2 = getTwoDimensionListIndex(maps, "+")
 87     visited = [[[0 for i in range(k+1)] for j in range(c)] for e in range(r)]
 88     """
 89     三维的visited列表
 90     [
 91         [[0, 0], [0, 0], [0, 0], [0, 0]], 
 92         [[0, 0], [0, 0], [0, 0], [0, 0]], 
 93         [[0, 0], [0, 0], [0, 0], [0, 0]], 
 94         [[0, 0], [0, 0], [0, 0], [0, 0]]
 95     ]
 96     """
 97     # 从这里出发,置状态为1,表示访问过
 98     visited[r1][c1][k] = 1
 99     rtn = bfs(r, c, k)
100     if rtn == 0:
101         print("-1")
102     else:
103         print("鸣人追上佐助最少需要花费的时间为:%d" % rtn)
104 
105 
106 if __name__ == '__main__':
107     main()
 
原文地址:https://www.cnblogs.com/an-wl/p/13360183.html