题解:先确定自由变量,然后枚举自由变量的值,注意剪枝。
#include<cmath> #include<cstring> #include<cstdio> #include<iostream> using namespace std; #define MAXN 230 int a[MAXN][MAXN], b[MAXN]; int index[MAXN], flag[MAXN]; //flag[i]==1表示b[i]是自由变量, index[i]记录第i个自由变量的下标 char str[MAXN]; int n, fnum, order; //fnum表示自由变量的数量,order是化简之后的举证的秩 int ans; int abl ( int x ) { return x >= 0 ? x : -x; } void Debug ( ) { int i , j; printf("Debug\n"); for ( i = 0; i < n; i++ ) { for ( j = 0; j <= n; j++ ) printf("%d ",a[i][j]); printf("\n"); } } /* x0 x1 x2 x3 x4 x5 b 0 0 1 0 1 1 1 1 1 0 0 0 0 1 0 1 2 0 0 0 0 0 1 0 3 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 以此矩阵为例矩阵简单推导一下,便可得下面的求值函数 order = 2, n = 6; x0, x2, x3 是自由变量; 先求x5: i = order-1 = 2, j = x + 1 = 6 ······ */ int cal () { int i, j, x, sum = 0; x = n - 1; for ( i = order - 1; i >= 0; i-- ) { while ( flag[x] && x >= 0 ) sum += b[x--]; if ( x >= 0 ) { b[x] = a[i][n]; for ( j = x + 1; j < n; j++ ) b[x] ^= ( a[i][j] && b[j] ); sum += b[x--]; } } return sum; } void dfs ( int k, int cnt ) { if ( cnt >= ans ) //剪枝 return; if ( k >= fnum ) { int tmp = cal(); if ( ans > tmp ) ans = tmp; return; } b[index[k]] = 0; dfs ( k + 1, cnt ); b[index[k]] = 1; dfs ( k + 1, cnt + 1 ); } int Gauss () { int i, j, row, col, mr; row = col = fnum = 0; while ( row < n && col < n ) { mr = row; for ( i = row + 1; i < n; i++ ) if ( abl(a[i][col]) > abl(a[mr][col]) ) mr = i; if ( mr != row ) for ( j = col; j <= n; j++ ) swap ( a[mr][j], a[row][j] ); if ( a[row][col] == 0 ) { flag[col] = 1; index[fnum++] = col; col++; continue; } for ( i = row + 1; i < n; i++ ) { if ( a[i][col] == 0 ) continue; for ( j = col + 1; j <= n; j++ ) a[i][j] ^= a[row][j]; } row++; col++; } //Debug(); order = row; for ( i = row; i < n; i++ ) if ( a[i][n] ) return -1; ans = MAXN; dfs ( 0, 0 ); return ans; } void init () { int i, j, k = n * n; int t1, t2, t3, t4; for ( i = 0; i < k; i++ ) { t1 = i / n; t2 = i % n; for ( j = 0; j < k; j++ ) { t3 = j / n; t4 = j % n; if ( abl(t1-t3) + abl(t2-t4) <= 1 ) a[i][j] = 1; } } } int main() { int t; scanf("%d",&t); while ( t-- ) { scanf("%d",&n); memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(flag,0,sizeof(flag)); init(); int i, j, k, res; k = n; n = n * n; i = 0; while ( k-- ) { scanf("%s",str); for ( j = 0; str[j] != '\0'; j++ ) { if ( str[j] == 'w' ) a[i][n] = 1; i++; } } //Debug(); res = Gauss (); if ( res == -1 ) printf("inf\n"); else printf("%d\n",res); } }