阿里笔试(走迷宫)

小强在玩一个走迷宫的游戏,他操控的人物现在位于迷宫的起点,他的目标是尽快的达到终点。每一次他可以选择花费一个时间单位向上或者向下或者向左或者向右走一格,或是使用自己的对称飞行器花费一个时间单位瞬移到关于当前自己点中心对称的格子,且每一次移动的目的地不能存在障碍物。具体来数说,设当前迷宫有n行m列,如果当前小强操控的人物位于点A(x, y),那么关于点A中心对称的格子B(x’, y’)满足x + x’ = n + 1且 y + y’ = m + 1。需要注意的是,对称飞行器最多使用5次。

输入描述:
第一行两个空格分隔的正整数n,m,分别代表迷宫的行数和列数。
接下来n行,每行一个长度为m的字符串来描述这个迷宫。
其中 .代表通路。 #代表障碍。 S代表起点。 E代表终点。 保证只有一个S和一个E。
2 <= n, m <= 500
输出描述:
仅一行一个整数表示从起点最小花费多少时间单位到达终点。
如果无法到达终点,输出-1。

由于要求最短的路径,个人认为BFS比较适合,BFS搜索到的第一个解一定是最优解。(在普通的广度优先算法里面,走过的节点就不会再走,由于本题加入了飞行次数,所以我认为走过的节点有可能需要再走一次,比如第一次走过这个节点的时候没有了飞行次数,而第二走过这个节点的时候还有一次飞行次数,那么第一次可能找不到解,第二次就可能找到)。于是加入了一个点飞行次数的记录,然后第二次走某个节点时如果飞行次数比第一次多,那么就表示可以再走

代码

import sys
from collections import deque
import copy
class node:
    def __init__(self, x, y, stp, cnt):
        self.x = x
        self.y = y
        self.stp = stp
        self.cnt = cnt

def check(x, y, m, n):
    if x>=0 and x<n and y>=0 and y<m:
        return True
    else:
        return False
dir = [[0,1], [0,-1], [1,0], [-1,0]]

def BFS(sx, sy, ex, ey, n, m, map):
    q = deque()
    st = node(sx, sy, 0, 5)
    vis = []
    for i in range(n):
        vis.append([])
        for j in range(m):
            vis[i].append(0)

    fly_count = []
    for i in range(n):
        fly_count.append([])
        for j in range(m):
            fly_count[i].append(0)
    
    vis[sx][sy] = 1
    q.append(st)
    while q:
        now = q.popleft()
        if now.x == ex and now.y == ey:
            return now.stp
        
        for i in range(4):
            nxt = copy.deepcopy(now)
            nxt.x = now.x + dir[i][0]
            nxt.y = now.y + dir[i][1]
            nxt.stp = now.stp + 1
            nxt.cnt = now.cnt
            if check(nxt.x, nxt.y, m, n) and (vis[nxt.x][nxt.y]==0 or vis[nxt.x][nxt.y]==1 and nxt.cnt>fly_count[nxt.x][nxt.y]) and (map[nxt.x][nxt.y]=='.' or map[nxt.x][nxt.y]=='E'):
                vis[nxt.x][nxt.y] = 1
                fly_count[nxt.x][nxt.y] = nxt.cnt
                q.append(nxt)
        if now.cnt >= 1:
            nxt = copy.deepcopy(now)
            nxt.x = n-1 - now.x
            nxt.y = m-1 - now.y
            
            nxt.stp = now.stp + 1
            nxt.cnt = now.cnt - 1

        if check(nxt.x, nxt.y, m, n) and (vis[nxt.x][nxt.y]==0 or vis[nxt.x][nxt.y]==1 and nxt.cnt>fly_count[nxt.x][nxt.y]) and (map[nxt.x][nxt.y]=='.' or map[nxt.x][nxt.y]=='E'):
                vis[nxt.x][nxt.y] = 1
                fly_count[nxt.x][nxt.y] = nxt.cnt
                q.append(nxt)
    return -1


if __name__=='__main__':
    map = [['#', 'S', '.', '.'], ['E', '#', '.', '.'],['#', '.', '.', '.'],['.', '.', '.', '.']]
    n = 4
    m = 4
    for i in range(len(map)):
        for j in range(len(map[0])):
            if map[i][j] == 'S':
                sx = i
                sy = j
            if map[i][j] == 'E':
                ex = i
                ey = j
    nxt = node(0,0,0,0)
    print(BFS(sx, sy, ex, ey, n, m, map))
    
        
        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值