关于黑白棋游戏题解

本文介绍了黑白棋游戏的解题思路,通过广度优先搜索(BFS)解决从初始状态转换到目标状态的最短着棋序列。讨论了状态的表示方法,包括将棋盘状态转化为16位二进制数,以及使用布尔数组和位运算优化处理。文章还提到了双向广度优先搜索在处理此类问题时的局限性和一位大牛的高效位运算解法。
摘要由CSDN通过智能技术生成
  

关于黑白棋游戏题解

焦祺 08-11-28

Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)

Problem Description

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

Input

包括若干组数据。第一行一个数n表示数据的组数。
每组数据共有8行。前四行是初始游戏状态,后四行是目标游戏状态。每行4个数分别表示该行放置的棋子颜色。“0”表示白棋;“1”表示黑棋。

Output

对应每组输入数据,输出如下结果:第一行是着棋步数n。接下来n行,每行4个数分别表示该步交换棋子的两个相邻方格的位置。例如,abcd表示将棋盘上(ab)处的棋子与(cd)处的棋子换位。

Sample Input

1

1111                                         

0000                                         

1110                                         

0010                                         

1010                                         

0101

1010

0101

Sample Output

4

1222

1424

3242

4344

 


 

由于没有设定好数据的范围,开始的时候没有能够得出正确答案

后来设好了居然TLE了!!

我就知道会这样,不过,要用什么方法优化呢~~

 

【网上某种解题思路】

这应该是这套题中最简单的一道,是一道典型的广度优先搜索,解决此题的关键就在于对状态的记录。我们发现这个矩阵我们可以看成成一个16位的二进制数,而且不会有重复。所以我们可以把它转化成一个十进制数,然后我们可以开一个布尔数组,用来记录,下标对应的状态是否存在。接着我们发现,如果当前矩阵中的某个位置与目标状态相同,我们就不需要再对它进行移动。而我们的转移是与上、下、左、右进行交换,如果相同,交换显然是没有必要的,否则一定不会更优。这样就可以进一步减少状态。经过这些处理,对于这个4*4的矩阵就完全没有问题了。

  当然,在具体处理时,我们也有着不同的方法。最简单的就是用整数矩阵,但是这个方法并不优。而根据标程,我们发现,其实用位运算进行处理效率会很高,另外用字符串效率也不错。

  这样,我们就可以完美的解决了。

 

并且得到一高手提示:

C(16,8)=16!/8!/8!  种状态

也就是说总共只有 10000多种状态

可以直接用BFS搜索

1111   1111

0000   1111

1111   1111

1111   0000

对于左边的状态,它对应的数是  1111000011111111 看成二进制数

它的十进制是: 1<<15 + 1<<14 + 1<<13 + 1<<12 + 0<<11 + 0<<10 + ...

也就是 Sigma(a[i]<<i) !!

 

于是我在结点里添加了一个整型用于记录

这样在判重和find的时候会减少一部分时间

代码如下:(或有少许BUG

#include <iostream>

using namespace std;

struct      Node

{

       int           n;

       bool p[4][4];

       int           last;

       int           sx,sy;

       int           dx,dy;

};

char a[4][4];

char b[4][4];

int           dir[4][2] = { {-1,0},{0,-1},{0,1},{1,0}};

int           counter;

Node    start;

Node       end;

Node       state[15000];

int           stateint[15000];

void bfs();

bool expand(Node& temp,int i,int j,int x,int y);    //扩展结点

bool repeat(Node temp,int tail);     //重复结点判断

bool finds(Node temp);//

void printpath(int tail);

void init();

void changetobit(Node& temp);

int main()

{

       int i,j,t,bit;

       scanf("%d",&t) ;

      

              getchar();

              while (t--)

              {

                     bit = 15;start.n =0;

                     for (i=0;i<4;i++)

                     {

                            for (j=0;j<4;j++)

                            {

                                   scanf("%c",&a[i][j]);

                                   if(a[i][j] == '1')

                                   {

                                          start.p[i][j] = 1;

                                          start.n += (1<<bit);

                                          bit--;

                                   }

                                   else

                                   {

                                          start.p[i][j] = 0;

                                          start.n += (0<<bit);

                                          bit--;

                                   }

                           

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值