Flip Game(枚举)
给十六个格子标上序号
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
便可以采用二进制记录不同的状态
0 1 0 0 0 1 1 0 0 0 1 1 0 1 1 1
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
此时便记录下了
14 10 9 5 4 2 1 0
最后采用十进制保存此时的状态 1表示‘b’,0表示‘w’,再做相应的翻转,既0 -> 1, 1 -> 0
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 char ma[5][5];//用于输入 5 int states[65535]={0};//(核心部分)记录状态因为最大为2^16-1=65535所以数组大小为65535 6 int step[65535]={0};//记录步数 7 int rear=0,front=0;//记录头与尾 8 bool vis[65535];//用于记录是否搜过 9 10 //输入,并记录初始状态,放入队列首位置 11 void shuru() 12 { 13 int i,state=0; 14 for(i=0;i<4;i++){ 15 cin>>ma[i]; 16 int j; 17 for(j=0;j<4;j++) 18 if(ma[i][j]=='b') 19 state|=1<<(i*4+j); 20 } 21 states[rear++]=state;//记录初始状态放入队列首 22 vis[state]=true;//记录已走过 23 } 24 25 //反转一个,并产生影响 26 int fanzhuan(int stat,int i) 27 { 28 int state=0; 29 state|=1<<i; 30 if(i%4!=0)state|=1<<(i-1); 31 if((i+1)%4!=0)state|=1<<(i+1); 32 if(i-4>=0)state|=1<<(i-4); 33 if(i+4<16)state|=1<<(i+4); 34 return (state^stat); 35 } 36 37 //BFS宽度遍历,搜索每种状态,不断放入队列中,找到后立即返回真(true) 38 bool bfs() 39 { 40 while(front<rear) 41 { 42 int state=states[front++];//取出队列头,记录此时状态 43 if(0==state||65535==state)//一旦找到,立即返回 44 { 45 cout<<step[state]<<"\n"; 46 return true; 47 } 48 int i; 49 for(i=0;i<16;i++)//遍历每种状态 50 { 51 int st; 52 st=fanzhuan(state,i); 53 if(!vis[st])//防止重复遍历 54 { 55 states[rear++]=st;//不可以的加到队列尾部 56 vis[st]=true; 57 step[st]=step[states[front-1]]+1;//步数加1 58 } 59 } 60 } 61 return false; 62 } 63 int main() 64 { 65 //freopen("in.txt","r",stdin); 66 //freopen("out.txt","w",stdout); 67 shuru(); 68 if(!bfs())cout<<"Impossible\n"; 69 return 0; 70 }