传送门
题目大意
有一个4*4的方格,每个方格中放一粒棋子,这个棋子一面是白色,一面是黑色。游戏规则为每次任选16颗中的一颗,把选中的这颗以及它四周的棋子一并反过来,当所有的棋子都是同一个颜色朝上时,游戏就完成了。现在给定一个初始状态,要求输出能够完成游戏所需翻转的最小次数,如果初始状态已经达到要求输出0。如果不可能完成游戏,输出Impossible。
思路
直接二进制枚举所有状态就好
代码
string cc[10];
int vis[10][10];//b++;
int solve(int num){
int count=0;
while(num){
num=num&(num-1);
count++;
}
return count;
}
int check(int n){//0-15
int a=n/4;
int b=n%4;
vis[a][b]++;
if(a-1>=0)
vis[a-1][b]++;
vis[a+1][b]++;
if(b-1>=0)
vis[a][b-1]++;
vis[a][b+1]++;
}
int main(){
for(int i=0;i<=3;i++){
for(int j=0;j<=3;j++){
cin>>cc[i][j];
}
}
int ans=inf;
for(int k=0;k<(1<<16);k++){
memset(vis,0,sizeof vis);
for(int i=0;i<16;i++){
if(k>>i&1){//表示第i位翻转了
check(i);
}
}
for(int i=0;i<=3;i++){
for(int j=0;j<=3;j++){
if(cc[i][j]=='b'){
vis[i][j]++;
}
}
}
int x=vis[1][1]%2;
int flag=1;
for(int i=0;i<=3;i++){
for(int j=0;j<=3;j++){
if(vis[i][j]%2!=x){
flag=0;
}
}
}
if(flag==1){
ans=min(ans,solve(k));
}
}
if(ans==inf){
puts("Impossible");
return 0;
}
printf("%d\n",ans);
}