Description
Input
Output
Sample Input
bwwb bbwb bwwb bwww
Sample Output
4
黑白棋翻转问题,搜索,枚举都可以做,这次用它来练习高斯消元做法
每个有关系的系数为1,每个棋子是否翻转确定了结果是0还是1,得到了异或方程组,使用高斯消元,找出自由元,然后转化为二进制后,枚举自由元,找出最优解。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; #define INF 0x3f3f3f3f int Map[20][20] , a[20] , min1 , x[20] , freex[20] ; char str[5][5] ; void getMap(int k) { int i , j ; memset(Map,0,sizeof(Map)) ; for(i = 0 ; i < 4 ; i++) { for(j = 0 ; j < 4 ; j++) { a[i*4+j] = (str[i][j] - '0') ^ k ; Map[i*4+j][i*4+j] = 1 ; if( i > 0 ) Map[i*4+j][i*4+j-4] = 1 ; if( i < 3 ) Map[i*4+j][i*4+j+4] = 1 ; if( j > 0 ) Map[i*4+j][i*4+j-1] = 1 ; if( j < 3 ) Map[i*4+j][i*4+j+1] = 1 ; } } return ; } void swap1(int p,int q) { int j , temp ; temp = a[p] ; a[p] = a[q] ; a[q] = temp ; for(j = 0 ; j < 16 ; j++) { temp = Map[p][j] ; Map[p][j] = Map[q][j] ; Map[q][j] = temp ; } return ; } int solve() { int i , j , k , t = 0 , num1 = 0 ; for(i = 0 ; i < 16 && t < 16 ; t++ , i++) { for(j = i ; j < 16 ; j++) if( Map[j][t] ) break ; if( j == 16 ) { freex[num1++] = t ; i-- ; continue ; } if( i != j ) swap1(i,j) ; for(j = i+1 ; j < 16 ; j++) { if( Map[j][t] ) { a[j] = a[j]^a[i] ; for(k = t ; k < 16 ; k++) Map[j][k] = Map[j][k] ^ Map[i][k] ; } } } for( ; i < 16 ; i++) if( a[i] ) return -1 ; if( num1 ) return num1 ; for(i = 15 ; i >= 0 ; i--) { x[i] = a[i] ; for(j = i+1 ; j < 16 ; j++) x[i] = x[i]^(Map[i][j]*x[j]) ; } return num1 ; } int f(int s) { int i , j , k , key , ans , min1 = INF ; getMap(s) ; key = solve() ; ans = 0 ; if( key == 0 ) { ans = 0 ; for(i = 0 ; i < 16 ; i++) ans += x[i] ; min1 = min(min1,ans) ; } else if( key > 0 ) { int temp = 1<<key ; for(int t = 0 ; t < temp ; t++) { memset(x,0,sizeof(x)) ; ans = 0 ; for(j = 0 ; j < key ; j++) if( t & (1<<j) ) { x[ freex[j] ] = 1 ; ans++ ; } for(i = 15 ; i >= 0 ; i--) { for(k = 0 ; k < 16 ; k++) if( Map[i][k] ) break ; x[k] = a[i] ; for(j = k+1 ; j < 16 ; j++) x[k] ^= (Map[i][j]*x[j]) ; ans += x[k] ; } min1 = min(min1,ans) ; } } return min1 ; } int main() { int i , j , min1 = INF , k , ans , temp ; for(i = 0 ; i < 4 ; i++) { scanf("%s", str[i]) ; for(j = 0 ; j < 4 ; j++) { if( str[i][j] == 'b' ) str[i][j] = '0' ; else str[i][j] = '1' ; } } ans = f(0) ; min1 = min(min1,ans) ; ans = f(1) ; min1 = min(min1,ans) ; if( min1 == INF ) printf("Impossible\n") ; else printf("%d\n", min1) ; return 0; }