都是差不多的意思 zoj给的时间比较多
题意是 一个4x4的棋盘 要求反转为全白或全黑 求最少次数
所有要说的都在代码里了
#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#define maxn (1<<16)-1
using namespace std;
int visit[maxn+5];
queue<int> q;
int flip(int state,int i,int j)
{
int a=(1<<(i*4+j));
state^=a;//按位异或 同则0 异则1 所以除去改变位之外 其他的状态不会变 比如:非改变位:元状态为1 与0异或得1 ;元状态为0与0异或得0
if(i-1>=0)
{
a=(1<<((i-1)*4+j));
state^=a;//up
}
if(i+1<4)
{
a=(1<<((i+1)*4+j));
state^=a;//down
}
if(j-1>=0)
{
a=(1<<(i*4+j-1));
state^=a;//left
}
if(j+1<4)
{
a=(1<<(i*4+j+1));
state^=a;//right
}
return state;//忘记return了emm
}
int bfs(int state)
{
/*
这个算法主要流程
第一层跑出每个翻转的状态 16次
第二层在每一个第一遍跑出来的状态的基础上再 跑16次 就是总次数变为16*16
之后以此类推
而超过16层之后就相当于又翻回来原来的状态
本质上就是优化穷举 穷举的话16^16有一大堆重复状态 这个的话 只有(1<<16) -1的状态量
*/
while(!q.empty()) q.pop();
q.push(state);
int step=0;
visit[state]=1;
while(!q.empty())
{
int g=q.size();
for(int k=0;k<g;k++)
{
int f=q.front();
q.pop();
if(step>16||f==0||f==maxn) return step;//如果 超过16次 0全白 maxn全黑 return
for(int i=0;i<4;i++)//在每个状态的基础上 再次枚举所有翻一遍的状况
{
for(int j=0;j<4;j++)
{
int t=flip(f,i,j);
if(!visit[t])
q.push(t);
visit[t]=1;
}
}
}
step++;
}
}
int main()
{
int T;
cin>>T;
bool flag1=true;
while(T--)
{
getchar();
memset(visit,0,sizeof(visit));
char map[10];
int k=0,state=0;//state也可以用数组每一行压缩成一个int
for(int i=0;i<4;i++)
{
scanf("%s",map);
for(int j=0;j<4;j++)
{
if(map[j]=='b')
state+=(1<<k);
k++;//控制位置
}
}
int ans=bfs(state);//初始状态传入
if(!flag1)
cout<<endl;
if(flag1)
{
flag1=false;
}
if(ans>16) cout<<"Impossible"<<endl;
else cout<<ans<<endl;
}
return 0;
}