POJ-1222 EXTENDED LIGHTS OUT(高斯消元)

题意:

给你一个5*6的矩阵,每个点上都有一个灯,按下f[i][j]的按钮,f[i][j]位置的灯的状态会改变,它上下左右的灯的状态也会改变(开变关,关变开)。

现在给出这个矩阵的初始状态,输出按下哪些按钮,使所有的灯都关闭。


做法:

利用高斯消元解异或方程组。

用x[i][j]表示第i行第j列的灯是否被按下

x[i][j] ^  x[i+1][j] ^  x[i-1][j] ^  x[i][j+1] ^  x[i][j-1]= f[i][j]

从给定的状态到全0的解=从全0状态到给定状态的解

用^和&&来代替实数高斯消元里的加减即可。

本题“认为”有唯一解就好了。

(注:引用了kuangbin的写法)


#include 
#include 
#include 
#include 
#include 
using namespace std;

const int MAXN = 50; //未知数数目
int equ, var;        //equ个方程,var个变元
int a[MAXN][MAXN];   //行数为equ,0~var列为系数,var列为得数
int x[MAXN];         //解集
int free_num;        //自由变元数量
int free_x[MAXN];    //自由变元,多解枚举时会用到

/*******************************************************
*               mod2高斯消元过程
*       返回-1无解,0惟一解,>0自由变元数目
*******************************************************/
int Gauss()
{
	int maxr, col, i, j, k;
	free_num = 0;
	for (k = 0, col = 0; kabs(a[maxr][col]))
				maxr = i;
		}
		if (a[maxr][col] == 0)
		{
			k--;
			free_x[free_num++] = col;	              //出现一个自由变元
			continue;
		}
		if (maxr != k)
		{
			for (j = col; j= 0; i--)  //惟一解,进行回代
	{
		x[i] = a[i][var];
		for (j = i + 1; j 0) a[(i - 1) * 6 + j][t] = 1;  //top
			if (i < 4) a[(i + 1) * 6 + j][t] = 1;  //bottom
			if (j > 0) a[i * 6 + j - 1]  [t] = 1;  //left
			if (j < 5) a[i * 6 + j + 1]  [t] = 1;  //right
		}
	for (i = 0; i < 30; i++)
		scanf("%d",&a[i][30]);
	Gauss();
	for (i = 0; i < 5; i++)
	{
		for (j = 0; j < 5; j++)
			printf("%d ", x[6 * i + j]);
		printf("%d\n",x[6*i+5]);
	}
}

int main()
{
	int i, T;
	scanf("%d", &T);
	for (i = 1; i <= T; i++)
	{
		printf("PUZZLE #%d\n", i);
		work();
	}
	return 0;
}


你可能感兴趣的:(ACM)