zoukankan      html  css  js  c++  java
  • 广度优先搜索-鸣人和佐助

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

    鸣人有一定数量的查克拉,每一个单位的查克拉可以打败一
    个大蛇丸的手下。假设鸣人可以往上下左右四个方向移动,
    每移动一个距离需要花费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()
     
  • 相关阅读:
    问题账户需求分析
    需求分析初学理解
    GitHub初步探索-1-使用本地代码管理工具,简化上传的过程
    软件工程概论-个人总结
    第二次冲刺-个人工作总结05
    第二次冲刺-个人工作总结04
    第二次冲刺-个人工作总结03
    第二次冲刺-个人工作总结02
    第二次冲刺-个人工作总结01
    第一次冲刺-个人工作总结10
  • 原文地址:https://www.cnblogs.com/an-wl/p/13360183.html
Copyright © 2011-2022 走看看