蓝桥杯:卡片换位【BFS】【Python实现】

题目描述

你玩过华容道的游戏吗?

这是个类似的,但更简单的游戏。

看下面 3 x 2 的格子

+---+---+---+

| A | * | * |

+---+---+---+

| B | | * |

+---+---+---+

在其中放 5 张牌,其中 A 代表关羽,B 代表张飞,* 代表士兵。

还有个格子是空着的。

你可以把一张牌移动到相邻的空格中去(对角不算相邻)。

游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。

输入描述

输入两行 6 个字符表示当前的局面

输出描述

一个整数,表示最少多少步,才能把 A B 换位(其它牌位置随意)

样例">样例">样例">样例">样例">样例">样例">样例">样例">输入输出样例

示例

输入

* A
**B

输出

17

这道题很像经典的BFS九宫格移动问题,可以用一维数组转换能二维数组的下标来移动解决

一维变二维下标 :x = index // 数组宽度, y = index % 数组宽度

二维变一维下标 :x * 数组宽度 + y

代码实现

import collections
def bfs(s,A_index,B_index):
    q = collections.deque()
    dic = {}                                    #使用字典记录每走一步的次数
    dic[s] = 0
    dist = [(0,1),(0,-1),(1,0),(-1,0)]
    q.append(s)
    
    while q:
        now = list(q.popleft())                 #把字符串转换成逐个添加进列表方便后面操作
        if now.index("A") == B_index and now.index("B") == A_index:
            return dic["".join(now)]            #如果A与B已经交换位置了,直接返回次数
        try:
            space = now.index(" ")
        except:
            return 10                           #测试样例有个没有空格,题目要求是每组都有移动用的空格的,可能是样例出错了
        x,y = space // 3, space % 3             #将一维数组转换成二维数组的索引,并不是实际创建二维数组
        distance = dic["".join(now)]            #记录当前步数
        for i in dist:
            tx,ty = i
            nx,ny = x + tx, y + ty
            if nx in [0,1] and ny in [0,1,2]:   #如果没有越界
                keynow = now.copy()
                keynow[space],keynow[nx*3 + ny] = keynow[nx*3 + ny],keynow[space]  #将二维数组的下标转换成一维数组的下标,互换空格与交换点的位置
                if "".join(keynow) not in dic.keys():     #如果交换的这个串第一次出现就创建
                    dic.setdefault("".join(keynow),distance + 1)
                    q.append(keynow)
    return -1

s1,s2 = input(),input()
s = s1+s2
A_index = s.index("A")                          #A的索引
B_index = s.index("B")                          #B的索引
print(bfs(s,A_index,B_index))

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值