题目:http://poj.org/problem?id=1753
题意:一块4*4的棋盘,黑白块不规律分布,翻动一个色块,其上下左右,都会被翻动,知道全黑全白为止。输出最小次数,达不到则输出“Impossible"
理解:每块棋盘只有两种表示 黑白 只有16个色块 可以用16位的二进制表示
1 1 1 1 1 2 3 4
1 1 1 1 转化为 5 6 7 8
1 1 1 1 9 10 11 12
1 1 1 1 13 14 15 16
位运算:异或(^)可以实现翻转 1^1=0 0^1=1
a. 1 1 1 1
1 1 1 1
1 1 1 1 表示为1100 1000 0000 0000 51200
1 1 1 1
b.
1 1 1 1
1 1 1 1
1 1 1 1 表示为1110 0100 0000 0000 58368
1 1 1 1
etc......
#include<iostream> const int MAX=999999; using namespace std; int arr[16]= {19,39,78,140,305,626,1252,2248,4880,8992,20032,35968,12544,29184,58368,51200};//只有一位是1,其余是零 int num[16]= {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};//对照操作的数 int main() { int i,j,value=0; int cmin=MAX; char c; for( i=0; i<16; i++) { cin>>c; if(c=='b') value+=num[i];//使黑色的位置 对应 为1 else continue; } for( i=0; i<65536; i++)//2^16 个数 i代表了每种翻牌方案 { int cnt=0; int cvalue=value; for(j=0; j<16; j++)//j 分别实现每个色块的翻牌操作 if(i&num[j])// 比如 0110 与 0010 则决定第二个色块的翻牌 0110 与0100 则决定第三个色块的翻牌 { cnt++; cvalue^=arr[j];//异或 实行翻牌 } if(cvalue==0||cvalue==65535) { if(cnt<cmin)cmin=cnt; } } if(cmin==MAX) cout<<"Impossible"; else cout<<cmin<<endl; return 0; }