题意:一个由1*1方块组成的m*m区域,想要将其全部涂成黄色。给定初始的颜色,每一次涂色会使周围的颜色反色(如同关灯游戏),问最少的涂色步数。
思路:第一次见识高斯消元,照猫画虎写出了代码,可是不知到为什么要这么做……
#include <stdio.h> #include <string.h> #define N 230 int s[N][N],ori[4][2]={1,0,-1,0,0,1,0,-1}; int n,m,T; int check(int x,int y){//判断(x,y)是否在区域内 if(x<0||y<0||x>=m||y>=m) return 0; return 1; } int gauss(){ int i,j,k,a,res=0; for(i = j = 0;i<n&&j<n;i++,j++){ k = i; while(!s[k][j] && k<n)//从第i行开始往下找第一行第j列为1的 k++; if(k == n){//如果没找到,下一列还从第i行开始找 i--; continue; } if(k!=i)//如果找到的不是第i行,则将第j列为1的换到第i行 for(a = j;a<=n;a++){ int temp = s[k][a]; s[k][a] = s[i][a]; s[i][a] = temp; } for(k = i+1;k<n;k++) if(s[k][j])//底下第j列为1的亦或 for(a = j;a<=n;a++) s[k][a] ^= s[i][a]; } k = i; for(i = k;i<n;i++)//无解 if(s[i][n]) return -1; for(i = k-1;i>=0;i--){ for(j = i+1;j<n;j++) s[i][n] ^= (s[i][j] && s[j][n]); if(s[i][n]) res++; } return res; } int main(){ freopen("a.txt","r",stdin); scanf("%d",&T); while(T--){ int i,j,k,x,y; char ch; memset(s,0,sizeof(s)); scanf("%d",&m); n = m*m; for(i = 0;i<m;i++){ getchar(); for(j = 0;j<m;j++){ ch = getchar(); if(ch == 'w') s[i*m+j][n] = 1; } } for(i = 0;i<m;i++) for(j = 0;j<m;j++){ s[i*m+j][i*m+j] = 1; for(k = 0;k<4;k++){ x = i+ori[k][0]; y = j+ori[k][1]; if(check(x,y)) s[x*m+y][i*m+j] = 1; } } k = gauss(); if(k==-1) printf("inf\n"); else printf("%d\n",k); } return 0; }