开心,总算过了,对于高斯消元的理解更深一步,这道题的重点在于,如果用高斯消元的话,最后一行是要枚举的,总共16种情况,因为不知道怎么枚举,当时卡了好久,其实在线性方程组中,我们可以当做缺少了四个方程,所以我们的过程就是枚举最后四个方程,然后一步一步往回带入。
其中要注意一点,就是最后的结果可以全是白面,也可以全是黑面,看了很多博客,说的解法都很麻烦,其实大可以不必,只要a数组加两列就行,将枚举的结果回带的时候,要多开两个数组记录下解空间,仅此而已。
/*#########################################################################
# File Name: poj_1753.cpp
# Author: CaoLei
# Created Time: 2015/7/21 14:02:56
#########################################################################*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
#include <queue>
#include <map>
using namespace std;
#define MAX(x,y) (((x)>(y))?(x):(y))
#define MIN(x,y) (((x)<(y))?(x):(y))
#define N 500010
#define pi acos(-1.0)
#define inf 100000000
typedef long long ll;
typedef unsigned long long ull;
char str[10];
int a[20][20];
int x1[20];
int x2[20];
int gauss(){
//高斯消元基本过程
int i = 0, line = 0;
for (;i<16;){
int p = line;
for (int j = line + 1; j<16; j++) if (a[line][i]<a[j][i]) p = j;
if (p != line) for (int j = 0; j <= 17; j++) swap(a[line][j], a[p][j]);
if (a[line][i] == 0){
i++;
continue;
}
for (int j = 0; j<16; j++){
if (j != line&&a[j][i]){
for (int k = i; k <= 17; k++) a[j][k] ^= a[line][k];
}
}
i++;
line++;
}
bool f1 = true, f2 = true;
for (int k = line; k<16; k++){
if (a[k][16]) f1 = false;
if (a[k][17]) f2 = false;
}
if (!f1&&!f2) return -1;
if(line==16) return 1;
int ans=16;
//这里记录下自由元的个数
int t=16-line;
//枚举16种解的情况
for(int i=0;i<(1<<t);i++){
for(int j=0;j<16;j++){
x1[j]=a[j][16];
x2[j]=a[j][17];
}
for(int j=0;j<t;j++){
if(i&(1<<j)){
x1[15-j]=1;
x2[15-j]=1;
}
else {
x1[15-j]=0;
x2[15-j]=0;
}
}
//回带的过程
for(int j=16-t-1;j>=0;j--){
int tmp1=0,tmp2=0;
for(int k=j+1;k<16;k++){
if(a[j][k]) {
tmp1^=x1[k];
tmp2^=x2[k];
}
}
//维护解空间
x1[j]^=tmp1;
x2[j]^=tmp2;
}
int c1=0,c2=0;
for(int ii=0;ii<16;ii++){
if(x1[ii]) c1++;
if(x2[ii]) c2++;
}
//更新最小值
ans=MIN(ans,MIN(c1,c2));
}
return ans;
}
int main(){
//freopen("in.txt","r",stdin);
int nn=20;
memset(a,0,sizeof(a));
for (int i = 0; i<4; i++){
scanf("%s", str);
for (int j = 0; j<4; j++){
int tmp = i * 4 + j;
if (str[j] == 'b') {
a[tmp][16] = 0;
a[tmp][17] = 1;
}
else{
a[tmp][16] = 1;
a[tmp][17] = 0;
}
a[tmp][tmp] = 1;
if (tmp>3) a[tmp - 4][tmp] = 1;
if (tmp<12) a[tmp + 4][tmp] = 1;
if (tmp % 4 != 0) a[tmp - 1][tmp] = 1;
if (tmp % 4 != 3) a[tmp + 1][tmp] = 1;
}
}
int ans = gauss();
if (ans == -1) printf("Impossible\n");
else printf("%d\n", ans);
return 0;
}