您的位置:首页 > 其它

POJ 1753 Flip Game (枚举 + 位运算)

2016-03-06 01:27 399 查看
题意:有一个4*4的棋盘,棋盘上有黑白格(两面分别为黑白色)。每一次你可以翻其中的一个格子,每翻一个格子,这个格子上下左右的格子(如果有)也会被翻,让你写一个程序,看最后将棋盘全部翻为白色格子或者是黑色格子用的最少的步数是多少?如果无法把所有格子都翻为白色或者是黑色,那么输出“Impossible”。



思路:

因为是4x4的棋盘,而且每个棋子只有黑或白2种状态(可以用0和1表示),所以整个棋盘的状态可以用一个整数value(只需低16位)来表示,(当value==0或者value==0xffff表示只有清一色黑或白)。

如果要改变某一位的状态,只要用1来跟那一位进行异或运算。

然后我发现:第一行的四个格子要翻转的状态(1表示翻转,0表示不翻转)分别是:
1100 1110 0111 0011
1000 0100 0010 0001
0000 0000 0000 0000
0000 0000 0000 0000
分别用0xc800, 0xe400, 0x7200, 0x3100来异或。后面的同理找出规律。
第二行用0x8c80, 0x4e40, 0x2720, 0x1310
第三行用0x08c8, 0x04e4, 0x0272, 0x0131
第四行用0x008c, 0x004e, 0x0027, 0x0013

#include<iostream>
#include<climits>
using namespace std;
const int M = INT_MAX;
typedef long long LL;
int flip[16]={0xc800, 0xe400, 0x7200, 0x3100, 0x8c80, 0x4e40, 0x2720, 0x1310, 0x08c8, 0x04e4, 0x0272, 0x0131, 0x008c, 0x004e, 0x0027, 0x0013};

int main(){
/*初始化check,用于检查一个二进制位上是否为1*/
int check[16];
for(int i=0;i<16;i++)
check[i]=(1<<(15-i));

int value=0, Min_step=M;
for(int i = 0; i < 16; i++){
char c;
cin >> c;                   //cin自动过滤回车
if(c == 'b')
value = (value<<1) + 1;
else value<<=1;
}

for(int i=0; i<(1<<16); i++){                   //i的二进制位中,1表示要翻,0表示不翻
int t_value=value, step=0;
for(int j=0; j<16; j++){                  //检查i从左到右每个二进制位是不是1
if(i&check[j]){                    //如果是1就要翻转value二进制中的该位
t_value^=flip[j];
step++;
}
}
if(t_value==0||t_value==0xffff){
if(step < Min_step) Min_step=step;
}
}
if(Min_step!=M) cout<<Min_step<<endl;
else cout<<"Impossible"<<endl;
return 0;
}


同类型题:POJ 2965
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: