题目链接:http://poj.org/problem?id=1753
构造号方程之后,先判断是否有解,之后在位运算枚举自由变量的值
代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#define pf printf
#define sf scanf
using namespace std;
const int maxn = 20,INF = 0x3f3f3f3f;
typedef int Matrix[maxn][maxn];
const int step[][2] = { {0,0} , {-1,0} , {1,0} , {0,1} , {0,-1} };
Matrix A,B;
int n;
void init(){
n = 16;
for(int i = 0;i < 4;++i){
for(int j = 0;j < 4;++j){
for(int k = 0;k < 5;++k){
int ni = i + step[k][0],nj = j + step[k][1];
if(ni >= 0 && ni < 4 && nj >= 0 && nj < 4){
A[ni * 4 + nj][i * 4 + j] = 1;
}
}
}
}
}
int ANS[maxn];
int Gauss(Matrix A){
int i,j,k,p;
for(i = j = 0;i < n && j < n;++j){
//选择交换行
k = i;
for(p = i + 1;p < n;++p) if(A[p][j] > A[k][j]) k = p;
if(A[k][j]){
for(p = 0;p <= n;++p) swap(A[i][p],A[k][p]);
for(k = i + 1;k < n;++k)
if(A[k][j] != 0){
for(p = 0;p <= n;++p) A[k][p] = ( A[k][p] - A[i][p] + 2 ) % 2 ;
}
i++;
}//如果当前列全为0 那么枚举当前行的下一列
}
// Debug();
//是否有解
for(k = i;k < n;++k) if(A[k][n]) return INF;
//枚举自由变量
int cnt = n - i,minAns = INF,tmpAns;
for(int st = 0;st < (1 << cnt);++st){
tmpAns = 0;
for(int j = n - 1;j >= i;--j) tmpAns += (ANS[j] = (st >> (16 - j - 1)) & 1);
//回代
for(int j = i - 1;j >= 0;--j){
int tmp = 0;
for(int p = j + 1;p < n;++p) tmp = (tmp + A[j][p] * ANS[p]) % 2;
ANS[j] = ( (A[j][n] - tmp) % 2 + 2 ) % 2;
tmpAns += ANS[j];
}
minAns = min(minAns,tmpAns);
}
return minAns;
}
char str[5];
int main(){
bool isInitRight = true;
init();
// Debug();
for(int i = 0;i < 4;++i){
sf("%s",str);
for(int j = 0;j < 4;++j){
if(str[j] == 'b') A[i * 4 + j][16] = 1,isInitRight = false;
else A[i * 4 + j][16] = 0;
}
}
memcpy(B,A,sizeof A);
for(int i = 0;i < n;++i) B[i][n] = B[i][n] ^ 1;
int ans;
ans = min(Gauss(A),Gauss(B));
if(ans == INF) pf("Impossible\n");
else pf("%d\n",ans);
}