黑白棋游戏 (BFS + 位运算初步运用)

该博客介绍了一种使用宽度优先搜索(BFS)解决黑白棋游戏最短变换路径问题的方法,结合位运算进行状态压缩和判重。通过将棋盘状态存储为16位二进制数,并利用位运算符进行棋子状态的获取和交换,降低了空间复杂度。同时,文章讨论了如何用位运算优化标记数组,进一步节省空间。
摘要由CSDN通过智能技术生成

题目描述

  黑白棋游戏的棋盘由4×4方格阵列构成。棋盘的每一方格中放有1枚棋 子,共有8枚白棋子和8枚黑棋子。这16枚棋子的每一种放置方案都构成一个游戏状态。在棋盘上拥有1条公共边的2个方格称为相邻方格。一个方格最多可有4 个相邻方格。在玩黑白棋游戏时,每一步可将任何2个相邻方格中棋子互换位置。对于给定的初始游戏状态和目标游戏状态,计算从初始游戏状态变化到目标游戏状态的最短走棋序列。

算法分析

状态的产生:每个位置可以跟上、下、左、右四个相邻位置进行交换,产生新的状态,但要考虑边界问题。

易知
水平方向的对换共有:3×4种,
垂直方向的对换共有:3×4种,
每个节点能够产生的新节点(状态)数最多为24种

容易想到的是我们要用BFS也就是广(宽)度优先搜索(点击查看模板)来进行模拟,但要解决一些问题:
数据如何存储?
节点如何判重?

关于棋盘状态的存储,我们考虑将每个棋盘保存为一个二维数组,在判定新节点的时候需要将新产生的棋盘与前面已有的棋盘逐个比对,但空间和时间消耗都比较大。因为棋盘本身并不复杂,每个格子都只有0和1两种状态值,于是可以考虑使用二进制位压缩状态,将棋盘用二进制位存储。

这样首先空间复杂度缩小32倍;状态判重也不用将数组各个元素进行对比,直接比较二进制数即可。

那么我们首先来学习一下位运算的基础知识:

认识位运算–基本运算符
运算 c++符号 解释
左移位 shl << 向左移位,低位补零,相当于乘二。如1<<2 = 4 =(100) ₂
右移位 shr >> 向右移位,高位补零,相当于除与二。如8>>2 = 4 = (100) ₂
按位与 and & 按二进制位与。如10&3 = (1010) ₂ &(0011) ₂ = (0010) ₂ = 2
按位或 or 按二进制位或。如10丨3=(1010) ₂ 丨(0011) ₂ =(1011) ₂ =11
按位取反not ~ 按二进制位取反。如~10= ~ (1010)2 = (0101)2
异或 xor ^ 按位加,不进位(相同返回1,不相同返回0)。 如10 ^ 3=(1010)2 ^ (0011)2=(1001)2

(其实还有同或)

那么,棋盘的状态存储可以转化为二进制,用一个16位的二进制数表示。因为每个位都要用到,对于C++而言可以设置无符号短整数类型(unsigned short int),刚好16位二进制,记录一个棋盘状态。

找到棋子状态

设坐标(x,y)坐标轴见下图 ,A为16位二进制表示的棋盘状态
取棋子状态则可以用位运算表达式:A &(1<<(x*4+y)) 。如下图:
请添加图片描述
对于棋盘而言,每次节点产生只需要枚举4×4棋盘每一个位置,如果这个位置是1,就可以进行四个方向的交换。对应位存储的状态,实际上就是枚举16位然后判断,考虑是否交换。

代码奉上
k
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值