关闭

翻转游戏题解

标签: C++bfs编程
177人阅读 评论(0) 收藏 举报
分类:

题目描述

翻转游戏是这样玩的:

有一张4*4的棋盘,在16个位置上每个位置放着一个棋子,棋子一面是黑色,另一面是白色,棋子或者白色面朝上,或者黑色面朝上。游戏的走法如下:每一步先选择一个位置,然后把该位置和上,下,左,右(不越界)相邻位置上的棋子翻转(白->黑,黑->白)。我们用w表示棋子白色面朝上,b表示黑色面朝上。

例如:考虑如下棋盘状态:

bwbw

wwww

bbwb

bwwb

当我们选择第三行,第一列的位置翻转时,棋盘变化为:

bwbw

bwww

wwwb

wwwb

游戏的目的是用最少的步数把全部棋子变为白色向上或黑色向上。

时限:1s

输入格式

4行由b和w组成的字符串描述的一个棋盘的初始状态。

输出格式

一个测试数据输出一行,为所需要的最少的翻转次数,如果无法翻转成目标状态,则输出’impossible’(小写,没有引号)。

样例输入(1

bwbw

wwww

bbwb

bwwb

样例输出(1

Impossible

样例输入(2

bwwb

bbwb

bwwb

bwww

样例输出(2

4

 

解题思路:

BFS搜索加哈希判重。将w设置为0,b设置为1。把16个位置的数据当做二进制数,将二进制转换为十进制数。

2^16=65536,用于判重的哈希数组并不会很大,可以实现。

类似的题目还有八数码问题,只不过八数码的哈希表为康托展开。八数码:https://www.rqnoj.cn/problem/70

AC代码:

#include<iostream>

#include<queue>

#include<cstring>

usingnamespace std;

 

typedefstruct table

{

   int pic[6][6];

}table;

 

tablestart;   //初始状态

 

intP[16]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};

boolvis[65536];  //状态数组

intdist[65536];

queue<table>Q;

 

//黑0 白1

charNegate(int ch)

{

   if(ch)

      return 0;

   return 1;

}

 

voidturn(int x,int y,table &T)

{

   T.pic[x][y]=Negate(T.pic[x][y]); //自身

   T.pic[x][y-1]=Negate(T.pic[x][y-1]);   //左侧

   T.pic[x][y+1]=Negate(T.pic[x][y+1]);   //右侧

   T.pic[x-1][y]=Negate(T.pic[x-1][y]);   //上侧

   T.pic[x+1][y]=Negate(T.pic[x+1][y]);   //下侧

}

 

intget_dec(table T)    //位压缩 

{

   int dec=0;

   int s=0;

   for(int i=4;i>0;--i)

   for(int j=4;j>0;--j)

   {

      dec+=T.pic[i][j]*P[s];

      s++;

   } 

   return dec;

}

 

intBFS()

{

   Q.push(start); //初始状态入队

   int st=get_dec(start);    //获取索引

   vis[st]=true;

   int front=1,rear=2;

   table Now;

   while(front<rear)

   {

      Now=Q.front();   //头结点出队

      Q.pop();

      int index=get_dec(Now);   //获取索引

      if(index==0||index==65535)   //找到终点

        return front;

      for(int i=0;i<16;++i)

      {

        int x=i/4+1;   //横坐标 

        int y=i%4+1;   //纵坐标

        table Next=Now;

        turn(x,y,Next);   //变换求下一步

        int ni=get_dec(Next);

        if(!vis[ni])

        {

           vis[ni]=true;

           Q.push(Next);

           dist[rear]=dist[front]+1;

           rear++;

        }

      }

      front++;

   }

   return -1;

}

intmain()

{

   for(int i=0;i<6;++i)

   for(int j=0;j<6;++j)

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

   memset(vis,0,sizeof(vis));

   for(int i=1;i<=4;++i)

   for(int j=1;j<=4;++j)

   {

      char ch;

      cin>>ch;

      if(ch=='w')

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

      else

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

   }

   int s=BFS();

   if(s!=-1)

      cout<<dist[s]<<endl;

   else

      cout<<"impossible"<<endl;

   return 0;

}

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:7935次
    • 积分:364
    • 等级:
    • 排名:千里之外
    • 原创:30篇
    • 转载:0篇
    • 译文:0篇
    • 评论:3条
    文章分类