题意:一个由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;
}