------------------------
/*
方法一:先算出所有状态对应的步数
POJ1753
首先需要明确:
1.棋盘最多只能走16步,2^16=65536因此可以枚举来解题(其实每格棋子最
多只可以翻转一次(实际是奇数次,但这没意义),只要其中一格重复翻了
2次(不论是连续翻动还是不连翻动),那么它以及周边的棋子和没翻动时的
状态是一致的,由此就可以确定这个棋盘最多只能走16步)
2.
每种状态可以转化为一个数,然后每次改变只要做对应的位操作。
4*4的b,w可以看作16为0,1组成的数字。
思路:
3.step[x],x表示输入棋盘状态所对应的数字,step[x]表示步数
4.0,65535是最终的状态,逆推求出只需要走一步的棋盘状态所对应的数:
分别翻动第1~16位,tmp数组记录下这16个数,step[xi]=1,step
[xi^65535]=1;别忘了全为b或者全为w都可以,如果x翻动一次就可以了,那
x^65535也只要翻动1次就可以了。
5.求出只需要走2步的棋盘状态所对应的数:
在走1步的基础上再走1步,相当于相互异或(思考下为什么是异或~)
6.求表示三步状态的数:把1步的跟2步的数异或,就是相当于在走了2步的
基础上再走一步。(需要防止重复)
7..以此类推,算出直至表示16步状态的数,改变step数组以他们为下标的
值
会发现有些数字转化为0,65535是需要一样的步数
383,2287,4919,7128,29262,36046,58407,,,
*/
#include<cstdio>
const int N=66536;
bool vist[N];
int step[N],tmp[N];
int top=0;
void Init_step1()
{
int i,cur,cur_t;
for(i=0;i<16;++i){
cur=cur_t=1<<i;
if(i%4!=0) cur|=cur_t>>1;
if((i+1)%4!=0) cur|=cur_t<<1;
if(i-4>=0)cur|=cur_t>>4;
if(i+4<16)cur|=cur_t<<4;
if(!vist[cur]){
vist[cur]=true,vist[cur^65535]=true;
tmp[top++]=cur;
step[cur]=1,step[cur^65535]=1;
// printf("----%d %d\ n",cur,cur^65535);
}
}
vist[0]=vist[65535]=true;
}
void Init_step2_16()
{
int stepp,ptr1,ptr2,pre,pre_top,cur;
for(stepp=2,pre=0,pre_top=16;stepp<17;++stepp){
for(ptr2=pre;ptr2<pre_top;++ptr2){
for(ptr1=0;ptr1<16;++ptr1){
cur=tmp[ptr2]^tmp[ptr1];
if(!vist[cur]){
vist[cur]=true;vist[cur^65535]=true;
tmp[top++]=cur;
step[cur]=stepp;
step[cur^65535]=stepp;
}
}
}
pre=pre_top;
pre_top=top;
printf("pre=%d pre_top=%d stepp=%d\n",pre,pre_top,stepp);
}
}
int main()
{
char str[5][5];
Init_step1();
Init_step2_16();
// printf("saass%d\n",step[38441]);
int i,j,x,cnt;
while(~scanf("%s",str[0])){
for(i=1;i<4;++i)
scanf("%s",str[i]);
for(i=0,cnt=15,x=0;i<4;++i)
for(j=0;j<4;++j,--cnt)if(str[i][j]=='b')x|=1<<cnt;
if(x==0||x==65535)
printf("0\n");
else if(!step[x])
puts("Impossible");
else
printf("%d\n",step[x]);
}
}
-----------------------------
-------------------------------
/*
方法2:考虑所有可能,暴力求解。分别翻动1~16位,翻动次数从1到16若还没有解,则为不可能
*/
#include<cstdio>
#include<cstring>
const int N=66536;
bool vist[N];
int step[N],tmp[N];
int top=1;
int change(int i,int cur)
{
int cur_t;
cur_t=1<<i;cur^=cur_t;
if(i%4!=0) cur^=cur_t>>1;
if((i+1)%4!=0) cur^=cur_t<<1;
if(i-4>=0)cur^=cur_t>>4;
if(i+4<16)cur^=cur_t<<4;
return cur;
}
int calc_ans(int x)
{
int i,cur,pre,stepp,ptr1,st,ed;
tmp[0]=x;
vist[x]=true;
for(stepp=1,st=0,ed=1;stepp<17;++stepp){
for(ptr1=st;ptr1<ed;++ptr1){
pre=tmp[ptr1];
for(i=0;i<16;++i){
cur=change(i,pre);
if(cur==0||cur==65535)return stepp;
if(!vist[cur]){
vist[cur]=true;
tmp[top++]=cur;
}
}
}
st=ed;ed=top;
}
return -1;
}
int main()
{
char str[5][5];
int i,j,x,cnt,ans=-1;
while(~scanf("%s",str[0])){
memset(vist,0,sizeof(vist));
top=1;
for(ans=-1,i=1;i<4;++i)
scanf("%s",str[i]);
for(i=0,cnt=15,x=0;i<4;++i)
for(j=0;j<4;++j,--cnt)if(str[i][j]=='b')x|=1<<cnt;
if(x==0||x==65535)
printf("0\n");
else{
ans=calc_ans(x);
if(ans<0)
puts("Impossible");
else
printf("%d\n",ans);
}
}
}