广度优先算法(BFS)_地牢逃脱

广度优先算法,又称宽度优先搜索或横向优先搜索。简称为BFS。

本质:图的遍历(或搜索)。

定义:从图中某个顶点出发,访问所有顶点,且每个顶点仅访问一次。(包括连通图和非连通图)

适用

  • 从A出发是否存在到达B的路径;
  • 从A出发到达B的最短路径(这个应该叫最少步骤合理);

图解:

1、访问顶点vi ;

2、访问vi 的所有未被访问的邻接点w1 ,w2 , …wk ;

3、依次从这些邻接点(在步骤②中访问的顶点)出发,访问它们的所有未被访问的邻接点; 依此类推,直到图中所有访问过的顶点的邻接点都被访问;

重要:有一个值来标志某一节点是否被访问过。

网易地牢逃脱

给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,
牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一些指定的步长遍历地牢,
要求每一步都不可以超过地牢的边界,也不能到达障碍上。地牢的出口可能在任意某个可以通行的位置上。
牛牛想知道最坏情况下,他需要多少步才可以离开这个地牢。 
输入描述:
每个输入包含 1 个测试用例。每个测试用例的第一行包含两个整数 n 和 m(1 <= n, m <= 50),表示地牢的长和宽。
接下来的 n 行,每行 m 个字符,描述地牢,地牢将至少包含两个 '.'。
接下来的一行,包含两个整数 x0, y0,表示牛牛的出发位置
(0 <= x0 < n, 0 <= y0 < m,左上角的坐标为 (0, 0),出发位置一定是 '.')。
之后的一行包含一个整数 k(0 < k <= 50)表示牛牛合法的步长数,
接下来的 k 行,每行两个整数 dx, dy 表示每次可选择移动的行和列步长(-50 <= dx, dy <= 50)
输出描述:
输出一行一个数字表示最坏情况下需要多少次移动可以离开地牢,如果永远无法离开,输出 -1。
以下测试用例中,牛牛可以上下左右移动,在所有可通行的位置.上,地牢出口如果被设置在右下角,
牛牛想离开需要移动的次数最多,为3次。
输入例子1:
3 3
...
...
...
0 1
4
1 0
0 1
-1 0
0 -1
输出例子1:
3

问题分解

出口在任意某个通行位置上,最坏情况下,多少步离开地牢。

最坏情况,刚开始理解为了,最多要多少步。其实非也,当出口不确定时,最坏情况是指,出口离起点最远,需要遍历所有点。

而是否最远,起点到出口的最短路径衡量。

遍历所有点+最短路径=广度优先算法

结构分析

需要进行坐标运算,封装point类可以简化代码

广度优先一般用队列实现。当起点入队之后,需要以队列是否为空为条件循环,while结构。

存储结构

地牢描述,是一个n*m的二维数组,存储该点可通行'.'或障碍物'x'

是否经过该点,用列表存储遍历过的下标。

路径,也就是走了几步,需要一个和地牢描述结构相同的二维数组保存。起始值均为1。当满足一个点为下一个点的可通行节点时,对应值增加1。

代码展示

import queue
class point(object):
    def __init__(self,x,y):
        self.x=x
        self.y=y
    @property
    def isOk(self):
        if  0<=self.x<n and 0<=self.y<m and  a[self.x][self.y]=='.':
            return True
        else:
            return False
    def go(self,d):
        return point(self.x+d[0],self.y+d[1])

if __name__=='__main__':
    n,m=[int(x) for x in input().split()]
    a=[]   #二维数组描述地牢
    use_point=0
    for i in range(n):
        a.append([x for x in input()])
        use_point+=a[i].count('.')
    x0,y0=[int(x) for x in input().split()]
    k=int(input())
    kli=[]  #存储步长
    for i in range(k):
        dx,dy=(int(x) for x in input().split())
        kli.append((dx,dy))
    print(n,m)
    print(a)
    print(x0,y0)
    print(k)
    print(kli)
    tt_li=[]
    start=point(x0,y0)
    q=queue.Queue()
    q.put(start)
    tt_li.append((start.x,start.y))
    eli=[[0 for j in range(m)]for i in range(n)]
    while not q.empty():
        temp=q.get()
        for i in kli:
            next_point=temp.go(i)
            ttemp=(next_point.x,next_point.y)
            if next_point.isOk and (ttemp not in tt_li):
                q.put(next_point)
                tt_li.append(ttemp)
                eli[next_point.x][next_point.y]=eli[temp.x][temp.y]+1
    if len(tt_li)==use_point:
        temppp=[]
        for x in eli:
            temppp.append(max(x))
        print(max(temppp))
    else:
        print(-1)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值