[湖大热身赛]Flip Five(BFS+状态压缩)

Flip Five
Time Limit: 2000ms, Special Time Limit:5000ms, Memory Limit:65536KB
Total submit users: 13, Accepted users: 8
Problem 13236 : No special judgement
Problem description

This is a logic puzzle in which you have a square grid of 3×3 cells. Each cell is initially either white or black. When you click on a square it flips, or toggles, the color of that square and the colors of its four immediate north, south, east and west neighbors that exist (they don’t exist if they would be outside the grid).

The problem is to find the minimum number of cell clicks to transform a grid of all white cells into the input grid (which is always possible). You cannot rotate the grid.

 


Input

The first value in the input file is an integer P (0 < P ≤ 50) on a line by itself giving the number of problems to solve.

For each of the P problems, 3 lines of 3 characters describe the input grid. The characters in the grid descriptions are ‘*’ (for black) and ‘.’ (for white).


Output

For each problem output a single integer giving the minimum number of clicks necessary to transform a grid of all white cells into the pattern given in the input.


Sample Input
2
*..
**.
*..
***
*..
..*
Sample Output
1
3

大三下学期重回热身赛和darkdream一起。图论大神LSS选择了退役找工作,剩下的比赛暂时就我和darkdream顶着invoker撸了。你说卡尔少了一个球还能刷新卡尔20连那么6么。。。言归正传。

此题题意跟小时候玩过的某个游戏一样。有一个3*3的方格,每个格子有黑白两面,点其中一个格子翻转,四周的格子跟着一起翻转,给出方格初始状态,问最少的次数使方格表面全变成白色。

想着反正才9个格子,给每个格子编号1-9。用二进制方法存下方格状态,BFS搜索翻转每个格子变化的状态,全白则ok。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <list>
#include <vector>
#include <ctime>
#define LL __int64
#define eps 1e-8
#define pi acos(-1)
using namespace std;
char p[5][5];
struct node{
	int k,t;
	node(int a,int b){k=a,t=b;
	}
};
queue<node> q;
int vis[3000];
int BFS(){
	while (!q.empty()){
		node a=q.front();
		q.pop();
		if (a.k==0) return a.t;
		for (int i=1;i<=3;i++)
			for (int j=1;j<=3;j++){
				int g1=a.k,g2=a.t+1;
				if (i==1){
					if (j==1){
						if (g1 & 1<<1) g1-=1<<1;
						else g1+=1<<1;
						if (g1 & 1<<2) g1-=1<<2;
						else g1+=1<<2;
						if (g1 & 1<<4) g1-=1<<4;
						else g1+=1<<4;
					}
					if (j==2){
						if (g1 & 1<<1) g1-=1<<1;
						else g1+=1<<1;
						if (g1 & 1<<2) g1-=1<<2;
						else g1+=1<<2;
						if (g1 & 1<<3) g1-=1<<3;
						else g1+=1<<3;
						if (g1 & 1<<5) g1-=1<<5;
						else g1+=1<<5;
					}
					if (j==3){
						if (g1 & 1<<3) g1-=1<<3;
						else g1+=1<<3;
						if (g1 & 1<<2) g1-=1<<2;
						else g1+=1<<2;
						if (g1 & 1<<6) g1-=1<<6;
						else g1+=1<<6;
					}
				}
				if (i==2){
					if (j==1){
						if (g1 & 1<<1) g1-=1<<1;
						else g1+=1<<1;
						if (g1 & 1<<5) g1-=1<<5;
						else g1+=1<<5;
						if (g1 & 1<<4) g1-=1<<4;
						else g1+=1<<4;
						if (g1 & 1<<7) g1-=1<<7;
						else g1+=1<<7;
					}
					if (j==2){
						if (g1 & 1<<5) g1-=1<<5;
						else g1+=1<<5;
						if (g1 & 1<<2) g1-=1<<2;
						else g1+=1<<2;
						if (g1 & 1<<4) g1-=1<<4;
						else g1+=1<<4;
						if (g1 & 1<<6) g1-=1<<6;
						else g1+=1<<6;
						if (g1 & 1<<8) g1-=1<<8;
						else g1+=1<<8;
					}
					if (j==3){
						if (g1 & 1<<3) g1-=1<<3;
						else g1+=1<<3;
						if (g1 & 1<<5) g1-=1<<5;
						else g1+=1<<5;
						if (g1 & 1<<6) g1-=1<<6;
						else g1+=1<<6;
						if (g1 & 1<<9) g1-=1<<9;
						else g1+=1<<9;
					}
				}
				if (i==3){
					if (j==1){
						if (g1 & 1<<4) g1-=1<<4;
						else g1+=1<<4;
						if (g1 & 1<<7) g1-=1<<7;
						else g1+=1<<7;
						if (g1 & 1<<8) g1-=1<<8;
						else g1+=1<<8;
					}
					if (j==2){
						if (g1 & 1<<5) g1-=1<<5;
						else g1+=1<<5;
						if (g1 & 1<<7) g1-=1<<7;
						else g1+=1<<7;
						if (g1 & 1<<8) g1-=1<<8;
						else g1+=1<<8;
						if (g1 & 1<<9) g1-=1<<9;
						else g1+=1<<9;
					}
					if (j==3){
						if (g1 & 1<<6) g1-=1<<6;
						else g1+=1<<6;
						if (g1 & 1<<8) g1-=1<<8;
						else g1+=1<<8;
						if (g1 & 1<<9) g1-=1<<9;
						else g1+=1<<9;
					}
				}
				if (vis[g1]==0) q.push(node(g1,g2));
			}
	}
}
int main(){
	int T;
	scanf("%d",&T);
	getchar();
	while (T--){
		memset(vis,0,sizeof(vis));
		gets(p[1]+1);
		gets(p[2]+1);
		gets(p[3]+1);
		int s=0;
		while (!q.empty()) q.pop();
		for (int i=1;i<=3;i++)
			for (int j=1;j<=3;j++)
				 	if (p[i][j]=='*')
						s+=1<<((i-1)*3+j);
		vis[s]=1;
		q.push(node(s,0));
		cout<<BFS()<<endl;
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值