poj1753 Flip Game 状态压缩+bfs

传送门:poj1753 Flip Game

题目的大意

在一个4*4的方格里面放黑或者白之一的卡片,当选中一个的,选中的那个就会翻转(如果是白色变为黑色,如果是黑色变为白色),伴随着他四周(上下左右)的的卡片也会翻转。就像下面这种情况题目中原图
如图所示,假设我们点击第三行第一列的时候不仅仅第三行第一列会变换状态,相应的第二行第一列,第三行第二列,第四行第一列也会变换,当然如果左边有的话也会变换状态。上图对应输入为:

bwbw 
wwww 
bbwb 
bwwb

当点击完第三行第一列的时候,会变为下面的状态:

bwbw 
bwww 
wwwb 
wwwb 

w代表white白色,b代表black黑色
输入:输入4*4只包含b或者w的矩阵
输出:通过几次能改变为全为白色或者全为黑色,如果不能输入impossible

解题思路

bfs+状态压缩
棋盘一共是有16方格,也就意味着有2^16(65535)种状态,
我们就假设黑色的棋子的状态为0,白色状态的棋子为1
每种方格只能被点击一次,比如我们在一个全为黑色点击了左上角的棋子,棋盘如下:

bbbb
bbbb
bbbb
bbbb

抽象为对应的状态棋盘就变为

0000
0000
0000
0000

点击左上角的棋子之后,状态棋盘就变为:

1100
1000
0000
0000

我们默认上面的和左边的高位,所以对应的二进制转换为十进制就变为51200
当点击其他的时候也是一样的原因。
有了这16中状态我们就可以通过异或来得到点击完相应的棋子之后的状态。

AC代码

#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<iostream>
#include<stack>
using namespace std;

struct Node{
    int state;
    int step;
};

bool visit[65536];

int change[16] = //这个是点击每个棋子的状态
{
     51200,58368,29184,12544,
     35968,20032,10016,4880,
     2248,1252,626,305,
     140,78,39,19
};

int bfs(int state)
{
     memset(visit,false,sizeof(visit));
    Node cur;
    Node next;
    int i,j;
    cur.step = 0;
    cur.state= state;
    visit[state] = true;
    queue<Node>q;
    q.push(cur);
    while(!q.empty())
    {
        cur = q.front();
        q.pop();
        if(cur.state == 0 || cur.state == 0xffff)//当全为白或者全为黑的情况
            return cur.step;
        for(i=0;i<16;i++)//一共有16个棋子
        {
            next.state = cur.state^change[i];//得到点击棋子之后的状态
            next.step = cur.step+1;          //步骤+1
            if(next.state == 0 || next.state == 0xffff)
                return next.step;
            if(visit[next.state])  //已经遍历过中的状态
                continue;
            visit[next.state] = true;//如果没有遍历过这种状态,改变为遍历过
            q.push(next);//添加到队列中
        }
    }
    return -1;

}


int main()
{
    int i,j,state,ans;
    char theMap[5][5];
    while(scanf("%s",theMap[0])!=EOF)
    {
        for(i=1;i<4;i++)
            scanf("%s",theMap[i]);
        state = 0;
        for(i=0;i<4;i++)    //变输入变把原棋盘的二进制计算出来
            for(j=0;j<4;j++)
            {
                state <<= 1;
                if(theMap[i][j] == 'b')
                    state+=1;
            }
        //printf("[%d]\n",state);
        ans = bfs(state);
        if(ans == -1)
            printf("Impossible\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值