【BFS+状态压缩】-POJ-1753-Flip Game

题目链接:http://poj.org/problem?id=1753

题目描述:

4*4的棋盘上翻棋,翻动一个子其上下左右四子也会被翻过去,问对于给出的一个4*4布局,是否能全翻成白棋或黑棋,如果能输出步数

解题思路:

之前的例会上学长用这个给我们当了状态压缩的栗子,当然,当时一点不明白学长在表达什么,碰巧遇到这题,自己就做了一把。

大概知道这样题换成二进制数储存状态,具体怎么对某个数在某一个二进制位上取反,我是今天才学的。

用这个” ^ “异或运算符,它的意思是把两个数换成二进制,两个数的相同位上如果相同结果是0,不同是1。(感谢于哲松大神和群里某学长指点)

例:

7是0111

8是1000

7 ^ 8=1111=15


好的,我们用111....1111(十六个)表示这十六个子,它们构成的相应十进位制数代表了此时的状态(cur),如果他们全是0或者全是1(即十进制65535)就是全变成一个颜色了。我又设了一个op数组,数组中存储的值为2的0~15次幂,存储翻某个子造成影响。比如:cur ^ op[ i ][ j ]就表示把 i 行 j 列的棋子翻了过来,(因为 1^0 = 1,0^0 = 0,0^1 = 1,1^1 = 0)之后都好办了。。写完居然还WA了好几遍,发现main函数结尾那不能写成if(bfs( start )==-1)什么的,但是改成ans接收一下就AC了。。不知道为啥,好吧以后就都拿ans接住得了。。= =

AC代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <queue>

using namespace std;

int op[5][5];
bool vis[70000];
queue<int> xx;
int dx[4]={1,-1,0,0},
    dy[4]={0,0,1,-1};

bool ok(int x,int y)
{
    if(x>=0&&x<4&&y>=0&&y<4)
        return 1;
    return 0;
}

int bfs(int st)
{
    while(!xx.empty())xx.pop();
    int step=0,cur,i,j,k;
    xx.push(st);
    while(!xx.empty())
    {
        int t=xx.size();
        while(t--)
        {
            cur=xx.front();
            xx.pop();
            vis[cur]=1;
            if(cur==0||cur==65535)
                return step;
            else
            {
                int next;
                for(i=0;i<4;i++)
                {
                    for(j=0;j<4;j++)
                    {
                        next=cur^op[i][j];
                        for(k=0;k<4;k++)
                        {
                            int tx,ty;
                            tx=i+dx[k];
                            ty=j+dy[k];
                            if(ok(tx,ty))
                                next=next^op[tx][ty];
                        }
                        if(!vis[next])
                        {
                            xx.push(next);
                            vis[next]=1;
                        }
                    }
                }
            }

        }
        step++;
    }
    return -1;
}

int input()
{
    memset(op,0,sizeof(op));
    memset(vis,0,sizeof(vis));
    int ans=0,cc=0;
    char grid[5][5];
    int i,j;
    for(i=0;i<4;i++)
        scanf("%s",grid[i]);
    for(i=0;i<4;i++)
        for(j=0;j<4;j++)
        {
            op[i][j]=pow(2,cc);
            if(grid[i][j]=='w')
                ans+=pow(2,cc);
            cc++;
        }
    return ans;
}

int main()
{
    int start,i,j;
    start=input();
    int ans=bfs(start);
    if(ans==-1)
        cout<<"Impossible"<<endl;
    else
        cout<<ans<<endl;
    return 0;
}

AC截图:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值