还是经典的高斯消元,和poj1753其实一模一样。要枚举自由变元得到最优解,不过这题不枚举自由变元使得自由变元都为0也能过,事实上必须要枚举的,数据太弱了~像1753不枚举自由变元的话就过不了。
我写的是枚举自由变元的。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int a[255][255] , x[255] ,xx[255] , equ , var ,n ; char s[22][22]; bool freex[255]; int dx[]={1,-1,0,0}; int dy[]={0,0,1,-1}; void debug() { int i,j; puts("debug"); for(i = 0;i < equ; i++) { for(j = 0;j < var+1;j ++) printf("%d ",a[i][j]); puts(""); } puts("end"); } void init() { memset(freex , true , sizeof(freex)); memset(a, 0, sizeof(a)) ; equ = var = n*n; int i,j,k; for(i = 0;i < n; i++) for(j = 0;j < n ; j++) { int st = i*n+j; if(s[i][j] == 'w') a[st][var] = 1; a[st][st] = 1; for(k = 0;k < 4; k++) { int xx = i+dx[k]; int yy = j+dy[k]; if(xx<0 || xx>=n || yy<0 || yy>=n) continue; int to = xx*n+yy; a[st][to] = 1; } } // debug(); } void gauss() { int i,j,k, row = 0 , col = 0; for(; row < equ && col < var; row++ , col++) { int maxr = row; for(i = row+1;i < equ; i++) if(a[i][col]) maxr = i; if(a[maxr][col]==0) { row--; continue; } if(row!=maxr) for(i = col;i < var+1;i ++) swap(a[maxr][i], a[row][i]); for(i = row+1;i < equ; i++) { if(a[i][col]==0) continue; for(j = col;j < var+1;j ++) a[i][j] ^= a[row][j]; } } // debug(); for(i = row;i < equ; i++) if(a[i][var]) { puts("inf"); return ; } if(row < var) { int ans = 11111111; for(i = row-1;i >= 0;i --) { int num = 0 , id; for(j = row;j < var; j++) if(freex[j] && a[i][j]) num++ , id = j; if(num > 1) continue; freex[i] = 0; } int num = var-row , d = 0; for(j = var-1;j >= 0 && d < num; j--) if(freex[j]) xx[d++] = j; int N = 1<<num; for(i = 0;i < N; i++) { for(j = 0;j < num ; j++) if(i & (1<<j)) x[xx[j]] = 1; else x[xx[j]] = 0; for(j = row-1;j >= 0; j--) { for(k = j;k < var; k++) if(a[j][k]) break; int id = k; x[id] = a[j][var]; for(k = id+1;k < var; k++) if(a[j][k] && x[k]) x[id] ^= 1; } int sum = 0; for(j = 0;j < var; j++) sum += x[j]; if(sum < ans) ans = sum; } printf("%d\n", ans); return ; } int ans = 0; for(i = var-1;i >= 0; i--) { x[i] = a[i][var]; for(j = i+1;j < var; j++) if(a[i][j] && x[j]) x[i] ^= 1; ans += x[i]; } printf("%d\n", ans); } int main() { int t,i; scanf("%d", &t); while(t--) { scanf("%d", &n); for(i = 0;i < n ; i++) scanf("%s", s[i]); init(); gauss(); } return 0; }