ZOJ-2050-Flip Game【状态压缩bfs】

来源:互联网 发布:linux 命令大全文库 编辑:程序博客网 时间:2024/05/17 17:14

2050-Flip Game


Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the other one is black and each piece is lying either it’s black or white side up. Each round you flip 3 to 5 pieces, thus changing the color of their upper side from black to white and vice versa. The pieces to be flipped are chosen every round according to the following rules:
Choose any one of the 16 pieces.
Flip the chosen piece and also all adjacent pieces to the left, to the right, to the top, and to the bottom of the chosen piece (if there are any).
Consider the following position as an example:

bwbw
wwww
bbwb
bwwb

Here “b” denotes pieces lying their black side up and “w” denotes pieces lying their white side up. If we choose to flip the 1st piece from the 3rd row (this choice is shown at the picture), then the field will become:

bwbw
bwww
wwwb
wwwb

The goal of the game is to flip either all pieces white side up or all pieces black side up. You are to write a program that will search for the minimum number of rounds needed to achieve this goal.

Input

The input consists of 4 lines with 4 characters “w” or “b” each that denote game field position.

Output

Write to the output a single integer number - the minimum number of rounds needed to achieve the goal of the game from the given position. If the goal is initially achieved, then write 0. If it’s impossible to achieve the goal, then write the word “Impossible” (without quotes).

This problem contains multiple test cases!

The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.

The output format consists of N output blocks. There is a blank line between output blocks.

Sample Input
2

bwbw
wwww
bbwb
bwwb

bwwb
bbwb
bwwb
bwww
Sample Output
Impossible

4

题目链接:ZOJ-2050

题目大意:4 * 4的方格,给出初始每个方格的颜色,每次操作能翻转3-5个方格的颜色(黑->白 | 白->黑),即翻转一个中心格子和旁边共边的格子的颜色。问,最少几次操作,使得全部格子的颜色都相同(全黑 or 全白)

题目思路:这道题看了题解,感觉位运算好厉害。

①queue元素:num为二进制记录状态,cnt记录这是第几次操作

②首先 将初始状态压缩为二进制表示,st |= (1 << (i * 4 + j)); //该位为b则为1 。并将初始状态压入队列

③bfs:取出首元素,然后暴力每一位作为中心点改变的情况。

④假设w点为中心点,ret为当前4*4格子的状态的二进制值, 利用异或的性质,(1 ^ 1 = 0, 0 ^ 1 = 1)巧妙的改变了状态,注意判断边界情况

int change(int ret,int w){    ret ^= (1 << w);    if (w % 4 && w > 0)  ret ^= (1 << (w - 1));      if (w % 4 < 3 && w < 15) ret ^= (1 << (w + 1));    if (w < 12) ret ^= (1 << (w + 4));    if (w > 3)  ret ^= (1 << (w - 4));      return ret;}

以下是代码:

#include <vector>#include <map>#include <set>#include <algorithm>#include <iostream>#include <cstdio>#include <cmath>#include <cstdlib>#include <string>#include <cstring>#include <queue>using namespace std;typedef long long ll;//状态压缩bfs  b->1 int st,vis[(1 << 17)];struct node{    int cnt,num;};queue <node> que;int change(int ret,int w){    ret ^= (1 << w);    if (w % 4 && w > 0)  ret ^= (1 << (w - 1));    if (w % 4 < 3 && w < 15) ret ^= (1 << (w + 1));    if (w < 12) ret ^= (1 << (w + 4));    if (w > 3)  ret ^= (1 << (w - 4));      return ret;}int bfs(){    while(!que.empty()) que.pop();    node tmp;    tmp.cnt = 0;    tmp.num = st;    vis[st] = 1;    que.push(tmp);    if (st == 0 || st == 65535) return 0;    while(!que.empty())    {        int front = que.front().num;        int cnt = que.front().cnt;        que.pop();        for (int i = 0; i < 16; i++)        {            int now = change(front,i);            if (now == 0 || now == 65535) return cnt + 1;            if (vis[now]) continue;             tmp.cnt = cnt+1;            tmp.num = now;            vis[now] = 1;            que.push(tmp);        }    }    return -1;}int main(){    int t;    cin >> t;    int ok = 0;    while(t--)    {        if (ok) cout << endl;        else ok = 1;        memset(vis,0,sizeof(vis));        st = 0;        string s[5];        for (int i = 0; i < 4; i++) cin >> s[i];        for (int i = 0; i < 4; i++)        {            for (int j = 0; j < 4; j++)            {                if (s[i][j] == 'b')                {                    st |= (1 << (i * 4 + j));  //该位为b则为1                 }            }        }         int ans = bfs();        if (ans == -1) cout << "Impossible\n";        else cout << ans << endl;    }     return 0;}
0 0
原创粉丝点击