poj1753 - Flip Game

133 篇文章 0 订阅

                                    想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410
                                     转载请注明出处:
http://blog.csdn.net/wangjian8006

题目大意:给一个4×4的期盘,b代表白色,w代表黑色,当翻一个棋子,那么这个棋子的上,下,左,右都会跟着翻过来
问翻最少的次数能够使棋盘达到全部是黑色或者全部是白色,如果不可能输出

解决思路:广搜+位运算。
因为棋子的状态只有白色和黑色,相当于二进制的0和1,所以可以用位运算。
我们用w表示1,b表示0,棋盘有16个方块,代表16位
那么用一个flag,又可以作为标记数组,代表棋盘状态是否被搜过,如果被搜过之后就不用再往后面搜,左上
角为最高位,右下为最低位,那么他们最大为0xFFFF(全部为1),而0xFFFF=65535,所以开一个标记数组不是很大
而flag=0代表没被找过,flag>0代表棋盘找到flag的时候所翻的最少次数。如果广搜之后找得到0x0或0xFFFF就返回
现在广搜的层数
而广搜在每一个节点,有16个点可以翻,所以它的周围有16个节点,那么翻第一个是什么情况,翻第二个是什么情况
一直到翻十六个是什么情况,其实就是说翻某一个点的时候,有哪些点要变,哪些点不变,这个时候打一个表,filp
代表每一个棋盘和flip取异或就可以了

 

/*
Memory 428K
Time   16MS 
*/


#include <queue>
#include <iostream>
using namespace std;

int  t;
int flag[70000];
int flip[16]={0xC800,0xE400,0x7200,0x3100,0x8C80,0x4E40,0x2720,0x1310,0x08C8,0x04E4,0x0272,0x0131,
0x008C,0x004E,0x0027,0x0013};

void bfs(){
	int v,i;
	queue<int> q;
	flag[t]=1;
	q.push(t);
	while(!q.empty()){
		v=q.front();
		q.pop();

		for(i=0;i<16;i++){
			t=v^flip[i];
			if(t==0x0 || t==0xFFFF) {flag[t]=flag[v]+1;return ;}

			if(!flag[t]){
				flag[t]=flag[v]+1;
				q.push(t);
			}
		}
	}
}

int main(){
	int i,j;
	char s[5];
	while(gets(s)){
		t=0;
		for(i=0;i<4;i++)
			if(s[i]=='w') t=(t<<1)+1;
			else t=t<<1;
		for(j=0;j<3;j++){
			gets(s);
			for(i=0;i<4;i++)
			if(s[i]=='w') t=(t<<1)+1;
			else t=t<<1;
        		}
		memset(flag,0,sizeof(flag));
		if(t==0x0 || t==0xFFFF) {printf("0\n");continue;}
		else bfs();
		if(flag[0xFFFF] || flag[0x0]) printf("%d\n",flag[t]-1);
		else printf("Impossible\n");
    }
    return 0;
}


 

 


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值