poj1753 Flip Game 位运算+科学枚举法 0ms无压力~

POJ 1753Flip Game

翻转游戏的玩法是一个双面的圆块放在16个正方形矩形4x4区域。每个圆块的一边是白色的,另一边是黑色的,每一轮选择一块,翻转所选的一块和所有相邻(上下左右,如果存在)的圆块。

以下图为例:

bwbw

wwww

bbwb

bwwb

“b”指的是黑色,”w”指白色。如果我们选择从第三行第一块翻转,结果为:

bwbw

bwww

wwwb

wwwb

游戏的目标是把所有的圆块的颜色弄成一样。请写一个程序,求出最少需要多少步

 

输入:

4*4的有w和b组成的矩阵

 

输出

如果存在翻转方案,则输出最少步数,如果不存在,则输出“Impossible”(不包括引号);

 

样例输入:

bwwb

bbwb

bwwb

bwww

 

样例输出:  4

如果固定了第一行,使第一行全部为一个颜色,那么可以确定第二行,第三行,第四行。那么翻第一行有2*2*2*2种方法,于是用枚举加位运算可以0ms秒过。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int t[20]={
    51200,58368,29184,12544,
    35968,20032,10016,4880,
    2248,1252,626,305,
    140,78,39,19,
};//  与t[0]异或表示翻第一行第一个,与t[1]异或表示翻第一行第二个..... 
int main()
{
    int count1,min1=100,ans=0,cnt=15;
    int a,b,c,d,i,j,k; 
    for(int i=0;i<4;i++)
    {
        char ch[10];
        scanf("%s",ch);
        for(j=0;j<4;j++)
            if(ch[j]=='w')
                ans|=(1<<cnt);
            cnt--;
        }
    }//处理输入数据,使之以2进制表示,1表示w,0表示b; 
    int temp;
    for(a=0;a<=1;a++)
    for(b=0;b<=1;b++)
    for(c=0;c<=1;c++)
    for(d=0;d<=1;d++)
    {
    	temp=ans;
    	count1=0;
    	if(a==1)temp^=t[0],count1++;//翻第一行第一个 
    	if(b==1)temp^=t[1],count1++;//翻第一行第二个,, 
    	if(c==1)temp^=t[2],count1++;//以此类推 
    	if(d==1)temp^=t[3],count1++;//不说了.... 
    	for(i=0;i<3;i++)//共有三行,0行,1行,2行 
    	   for(j=1;j<=4;j++)//共有四列,1列,2列,3列,4列 
    	    if((temp&(1<<((16-4*i-j))))==0)
    	    {
    	    	temp^=t[i*4+j+3];//第i行第j列是0,翻第i+1行第j列让第i行第j列变为1 
				count1++;
    	    }
    	if((temp&15)==15)min1=min(min1,count1);
    }//枚举第一行..把全部变成1,也就是黑色 
    for(a=0;a<=1;a++)
    for(b=0;b<=1;b++)
    for(c=0;c<=1;c++)
    for(d=0;d<=1;d++)
    {
    	temp=ans;
    	count1=0;
    	if(a==1)temp^=t[0],count1++;
    	if(b==1)temp^=t[1],count1++;
    	if(c==1)temp^=t[2],count1++;
    	if(d==1)temp^=t[3],count1++;
    	for(i=0;i<3;i++)
    	   for(j=1;j<=4;j++)
    	    if((temp&(1<<(16-4*i-j)))>0)temp^=t[i*4+j+3],count1++;
    	if((temp&15)==0)min1=min(min1,count1);
    }//枚举第二行,把全部变成2,也就是白色 
    if(min1!=100)cout<<min1;//找最小值 
    else cout<<"Impossible";
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值