poj 1753
地址:http://poj.org/problem?id=1753
题意:黑白棋,翻动一个格子,周围相连的格子都翻转,问最少几次使所有棋子颜色相同。
mark:正解高斯消元,第一次写,写了两天,终于理解并ac了~
代码:
#include <stdio.h> #include <string.h> int g[20][20]; int min(int a, int b) {return a < b ? a : b;} int find(int i) { int j; for(j = i; j < 17; j++) if(g[j][i]) return j; return 0; } void swap(int i, int j) { int k; for(k = 1; k < 19; k++) g[i][k] ^= g[j][k] ^= g[i][k] ^= g[j][k]; } void init() //初始化关系矩阵 { int i,j,k,x,y,tab[4][2] = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}}; memset(g, 0, sizeof(g)); for(i = 0; i < 4; i++) for(j = 1; j < 5; j++) { g[i*4+j][i*4+j] = 1; for(k = 0; k < 4; k++) { x = i+1+tab[k][0]; y = j+tab[k][1]; if(x > 0 && x < 5 && y > 0 && y < 5) g[i*4+j][(x-1)*4+y] = 1; } } } void init2(int b[][20]) //初始化增广矩阵并化简 { int i,j,k; for(i = 1; i < 17; i++) { g[i][17] = b[0][i]; g[i][18] = b[1][i]; } /* for(i = 1; i < 17; i++) { for(j = 1; j < 19; j++) printf("%d", g[i][j]); printf("\n"); } printf("\n");*/ for(i = 1; i < 17; i++) { j = find(i); if(!j) continue; if(j != i) swap(i, j); for(j = i+1; j < 17; j++) { if(j != i && g[j][i]) for(k = 1; k < 19; k++) g[j][k] ^= g[i][k]; } } /* for(i = 1; i < 17; i++) { for(j = 1; j < 19; j++) printf("%d", g[i][j]); printf("\n"); }*/ } void solve() { int i,j,k,f1,f2,cnt1,cnt2,min1,min2; int x1[20],x2[20]; f1 = f2 = 0; min1 = min2 = 10000000; for(i = 13; i < 17; i++) //打印增广矩阵化简后矩阵,可观察到有四行全为0 { if(f1 && f2) break; if(g[i][17]) f1 = 1; if(g[i][18]) f2 = 1; } if(f1 && f2) { printf("Impossible\n"); return ; } for(i = 0; i < 16; i++) { cnt1 = cnt2 = 0; memset(x1, 0, sizeof(x1)); memset(x2, 0, sizeof(x2)); for(j = 0; j < 4; j++) { x1[13+j] = x2[13+j] = (i & (1 << j)) ? 1 : 0; //这个地方找了好半天,一开始直接是正数或者0了,然后一直wa。。。 if(x1[13+j]) cnt1++,cnt2++; } for(j = 12; j > 0; j--) { for(k = j+1; k < 17; k++) { if(!f1) x1[j] ^= (x1[k] * g[j][k]); if(!f2) x2[j] ^= (x2[k] * g[j][k]); } if(!f1) { x1[j] ^= g[j][17]; if(x1[j]) cnt1++; } if(!f2) { x2[j] ^= g[j][18]; if(x2[j]) cnt2++; } } if(!f1) min1 = min(min1, cnt1); if(!f2) min2 = min(min2, cnt2); } printf("%d\n", min(min1, min2)); } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); char a[5][5]; int b[2][20]; int i,j,k; while(~scanf("%s", a[0])) { init(); memset(b, 0, sizeof(b)); for(i = 1; i < 4; i++) scanf("%s", a[i]); for(i = 0, j = 1; i < 4; i++) for(k = 0; k < 4; k++) { b[0][j] = (a[i][k] == 'b'); b[1][j++] = (a[i][k] == 'w'); } init2(b); solve(); } return 0; }