POJ 1753 Flip Game

状态压缩+广搜就可以了.

用0表示w,1表示b,16位2进制最大是65535.也就是说全黑或全白的状态是0和65535.

接下来广搜就可以了

一开始大于等于号忘了写等于号导致WA了好几次..囧..

#include <cstdio>
#include <queue>
#include <string.h>
using namespace std;
int vi[65536];
int f(int s,int j){
	//1 xor 0 =1,1 xor 1 = 0 状态改变
	//0 xor 0 =0,0 xor 1 = 1 状态不变 
	s^=(1<<j);
	if(j/4!=0)s^=1<<(j-4);//不是第一行 
	if(j/4!=3)s^=1<<(j+4);//不是最后一行 
	if(j%4!=0)s^=1<<(j-1);//不是第一列 
	if(j%4!=3)s^=1<<(j+1);//不是最后一列 
	return s;
}
int bfs(int x){
	if(x==0||x==65535)return 0;//初始就已达到状态 
	queue<int> qu;
	qu.push(x);
	vi[x]=1;
	int step=0;
	int pos=0,epos=1;
	while(1){
		int s2=epos;
		step++;
		for(int i=pos;i<epos;i++){//遍历这一层 
			int s=qu.front();
			qu.pop();
			for(int j=0;j<16;j++){//16个灯 
				int next=f(s,j);
				if(next==0||next==65535)return step;//达到状态 
				if(vi[next]==0){
					vi[next]=1;
					qu.push(next);
					s2++;
				}
			}	
		}
		if(pos==epos)return -1;//这一层便利中没有加入新状态,不能向下搜索了 
		pos=epos;
		epos=s2;
	}
	return -1;
}
int main(){
	char line[6];
	int st=0,res;
	memset(vi,0,sizeof(vi));
 	for(int i=0;i<4;i++){
	 	scanf("%s",line);
		for(int j=0;j<4;j++){
			if(line[j]=='b')st+=1<<(4*i+j);
		}	
	}
	if((res=bfs(st))>=0)printf("%d\n",res);
	else printf("Impossible\n"); 
	return 0;
} 


你可能感兴趣的:(POJ 1753 Flip Game)