Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 5352 | Accepted: 2588 |
Description
Input
Output
Sample Input
2 3 yyy yyy yyy 5 wwwww wwwww wwwww wwwww wwwww
Sample Output
0 15
题意:
一个n*n 的木板,每个格子都可以染成白色和黄色,一旦我们对某个格子染色,其上下左右都将改变颜色
求将所有的格子染成黄色最少需要几次,若不能则输出inf。
当有多个自由变元时,需要进行枚举求出最小值
/* poj1681 类似于一元开关问题。把二维矩阵转换成一维矩阵来看。 在求出答案之后,对于有很多解的考虑枚举自由变元来求解 最小值 */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; typedef long double ld; using namespace std; const int maxn = 300; int equ,var; int a[maxn][maxn]; int x[maxn]; int free_x[maxn]; int free_num; int Gauss() { int max_r,col,k; free_num = 0; for(k = 0,col = 0; k < equ && col < var; k++,col++) { max_r = k; for(int i = k+1; i < equ; i++) { if(abs(a[i][col]) > abs(a[max_r][col])) max_r = i; } if(a[max_r][col] == 0) { k --; free_x[free_num++] = col; continue; } if(max_r != k) { for(int j = col; j < var+1; j++) swap(a[k][j],a[max_r][j]); } for(int i = k + 1; i < equ; i++) { if(a[i][col] != 0) { for(int j = col; j < var+1; j++) a[i][j] ^= a[k][j]; } } } for(int i = k; i < equ; i++) if(a[i][col] != 0) return -1; if(k < var) return var-k; for(int i = var-1; i >= 0; i--) { x[i] = a[i][var]; for(int j = i +1; j < var; j++) x[i] ^= (a[i][j] && x[j]); } return 0; } int n; void ini() { memset(a,0,sizeof(a)); memset(x,0,sizeof(x)); equ = n*n; var = n*n; for(int i = 0;i < n;i++) { for(int j = 0;j < n;j++) { int tt = i*n+ j; a[tt][tt] =1; if(i > 0) a[(i-1)*n+j][tt] = 1; if(i < n-1) a[(i+1)*n+j][tt] = 1; if(j > 0) a[tt-1][tt] = 1; if(j < n-1) a[tt+1][tt] =1; } } } char str[30][30]; /* 2 3 yyy yyy yyy 5 wwwww wwwww wwwww wwwww wwwww */ int main() { int T; char color; scanf("%d",&T); while(T--) { scanf("%d",&n); ini(); for(int i = 0; i < n; i++) { scanf("%s",str[i]); for(int j = 0; j < n; j++) { if(str[i][j] == 'y') a[i*n+j][n*n] = 0; else a[i*n+j][n*n] = 1; } } int t = Gauss(); if(t == -1) { printf("inf\n"); } else if(t == 0) { int ans = 0; for(int i = 0; i < n*n; i++) ans += x[i]; printf("%d\n",ans); } else { int ans = 0x3f3f3f3f; int tot = (1 << t); for(int i = 0; i < tot; i++) { int cnt = 0; for(int j = 0; j < t; j++) { if(i & (1 << j)) { cnt ++; x[free_x[j]]= 1; } else x[free_x[j]]= 0; } for(int j = var-t-1; j >= 0; j--) { int dex; for(dex = j; dex < var; dex++) if(a[j][dex]) break; x[dex] = a[j][var]; for(int l = dex +1; l <var ; l++) { if(a[j][l]) x[dex] ^= x[l]; } cnt += x[dex]; } ans = min(ans,cnt); } printf("%d\n",ans); } } return 0; }