BFS--最短路径:864.获取所有钥匙的最短路径

给定一个二维网格 grid。 "." 代表一个空房间, "#" 代表一堵墙, "@" 是起点,("a", "b", ...)代表钥匙,("A", "B", ...)代表锁。

我们从起点开始出发,一次移动是指向四个基本方向之一行走一个单位空间。我们不能在网格外面行走,也无法穿过一堵墙。如果途经一个钥匙,我们就把它捡起来。除非我们手里有对应的钥匙,否则无法通过锁。

假设 K 为钥匙/锁的个数,且满足 1 <= K <= 6,字母表中的前 K 个字母在网格中都有自己对应的一个小写和一个大写字母。换言之,每个锁有唯一对应的钥匙,每个钥匙也有唯一对应的锁。另外,代表钥匙和锁的字母互为大小写并按字母顺序排列。

返回获取所有钥匙所需要的移动的最少次数。如果无法获取所有钥匙,返回 -1 。

 

示例 1:

输入:["@.a.#","###.#","b.A.B"]
输出:8
示例 2:

输入:["@..aA","..B#.","....b"]
输出:6
 

提示:

1 <= grid.length <= 30
1 <= grid[0].length <= 30
grid[i][j] 只含有 '.', '#', '@', 'a'-'f' 以及 'A'-'F'
钥匙的数目范围是 [1, 6],每个钥匙都对应一个不同的字母,正好打开一个对应的锁。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-path-to-get-all-keys
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution:
    def shortestPathAllKeys(self, grid: List[str]) -> int:
            from queue import Queue

            m = len(grid)
            n = len(grid[0])

            q = Queue()
            start_i, start_j = -1,-1
            key_num = 0#钥匙的总数

            for i in range(m):
                for j in range(n):
                    if(grid[i][j] == '@'):
                        start_i, start_j = i,j
                    if(grid[i][j].islower()):
                        key_num += 1

            q.put((start_i,start_j,(),0))#tuple(当前行数,当前列数,当前钥匙,当前开销)
            best_stat = {(start_i,start_j,()):0}#字典类型,key=(当前行数,当前列数,当前钥匙)的最小开销
            while not q.empty():
                cur_i,cur_j,keys,cost = q.get()#取当前队列头部的元素
                if len(keys) == key_num:
                    return cost
                for ii,jj in [(cur_i - 1,cur_j),(cur_i + 1,cur_j),(cur_i,cur_j - 1),(cur_i,cur_j + 1)]:
                    if(ii >=0 and ii < m and jj >= 0 and jj < n):
                        if grid[ii][jj] in ['@','.']:
                            if (ii,jj,keys) not in best_stat or cost + 1 < best_stat[(ii,jj,keys)]:
                                best_stat[(ii,jj,keys)] = cost + 1
                                q.put((ii,jj,keys,cost + 1))
                        if grid[ii][jj].islower():
                            #将新取得的钥匙加入到set中
                            new_keys = tuple(set(keys) | {grid[ii][jj]})
                            if (ii,jj,new_keys) not in best_stat or cost + 1 < best_stat[(ii,jj,new_keys)]:
                                best_stat[(ii,jj,new_keys)] = cost + 1
                                q.put((ii,jj,new_keys,cost + 1))
                            #将大写字母转换为小写字母并与其判断是否有钥匙
                        if grid[ii][jj].isupper() and chr(ord(grid[ii][jj]) - ord('A') + ord('a')) in keys:
                            if (ii,jj,keys) not in best_stat or cost + 1 < best_stat[(ii,jj,keys)]:
                                best_stat[(ii,jj,keys)] = cost + 1
                                q.put((ii,jj,keys,cost + 1))

            return -1

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值