poj 1681 高斯消元(方形涂色)

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


你可能感兴趣的:(poj 1681 高斯消元(方形涂色))