POJ 1222 高斯消元法解开关问题

#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 30;
int inp[maxn + 5][maxn + 5], kase, T;
void gauss()
{
	for (int i = 0; i < maxn; i++)
	{
		int k = i;
		while (k < maxn && !inp[k][i])k++;
		for (int j = 0; j <= maxn; j++)
			std::swap(inp[i][j], inp[k][j]);
		for (int j = 0; j < maxn; j++)
			if (i != j && inp[j][i])
				for (int p = 0; p <= maxn; p++)
					inp[j][p] = inp[i][p] ^ inp[j][p];
	}
}
int main(int argc, char const *argv[])
{
	scanf("%d", &T);
	while (T--)
	{
		memset(inp, 0, sizeof(inp));
		for (int i = 0; i < maxn; i++)
			scanf("%d", &inp[i][maxn]), inp[i][i] = 1;
		for (int i = 0; i < maxn; i++)
		{
			if (i % 6 != 0) inp[i - 1][i] = 1;
			if (i % 6 != 5) inp[i + 1][i] = 1;
			if (i > 5) inp[i - 6][i] = 1;
			if (i < 24) inp[i + 6][i] = 1;
		}
		gauss();
		printf("PUZZLE #%d\n", ++kase);
		for (int i = 0; i < maxn; i++)
			printf("%d%c", inp[i][maxn], i % 6 == 5 ? '\n' : ' ');
	}
	return 0;
}

楼上为简洁版,楼下为套用模板的版本。

#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 30;
int inp[maxn + 5][maxn + 5], kase, T;
// void gauss()
// {
// 	for (int i = 0; i < maxn; i++)
// 	{
// 		int k = i;
// 		while (k < maxn && !inp[k][i])k++;
// 		for (int j = 0; j <= maxn; j++)
// 			std::swap(inp[i][j], inp[k][j]);
// 		for (int j = 0; j < maxn; j++)
// 			if (i != j && inp[j][i])
// 				for (int p = 0; p <= maxn; p++)
// 					inp[j][p] = inp[i][p] ^ inp[j][p];
// 	}
// }
int equ, var, x[maxn], free_num, free_x[maxn];
int gauss()
{
	int max_r, col, k;
	free_num = 0;
	for (k = 0, col = 0; k < equ && col < var; k++, col++)
	{
		max_r = k;
		for (int i = k + 1; i < equ; i++)
			if (abs(inp[i][col]) > abs(inp[max_r][col]))
				max_r = i;
		if (inp[max_r][col] == 0)
		{
			k--; free_x[free_num++] = col;
			continue;
		}
		if (max_r != k)
			for (int j = col; j < var + 1; j++)
				std::swap(inp[k][j], inp[max_r][j]);
		for (int i = k + 1; i < equ; i++)
			if (inp[i][col] != 0)
				for (int j = col; j < var + 1; j++)
					inp[i][j] ^= inp[k][j];
	}
	for (int i = k; i < equ; i++)
		if (inp[i][col] != 0)
			return -1;
	if (k < var) return var - k;
	for (int i = var - 1; i >= 0; i--)
	{
		x[i] = inp[i][var];
		for (int j = i + 1; j < var; j++)
			x[i] ^= (inp[i][j] && x[j]);
	}
	return 0;
}
int main(int argc, char const *argv[])
{
	scanf("%d", &T);
	while (T--)
	{
		memset(inp, 0, sizeof(inp));
		for (int i = 0; i < maxn; i++)
			scanf("%d", &inp[i][maxn]), inp[i][i] = 1;
		for (int i = 0; i < maxn; i++)
		{
			if (i % 6 != 0) inp[i - 1][i] = 1;
			if (i % 6 != 5) inp[i + 1][i] = 1;
			if (i > 5) inp[i - 6][i] = 1;
			if (i < 24) inp[i + 6][i] = 1;
		}
		equ = 30, var = 30;
		gauss();
		printf("PUZZLE #%d\n", ++kase);
		for (int i = 0; i < maxn; i++)
			printf("%d%c", x[i], i % 6 == 5 ? '\n' : ' ');
	}
	return 0;
}

给你一个5行6列的矩阵分别表示30个灯,矩阵inp[i][j]=1表示灯亮着, =0表示灯没亮。设解决方案为press[][]:press[i][j]=1表示按一下,=0表示不按。使得最后状态为所有灯都熄灭。通过分析,可知:按按钮的顺序没有关系,每个按钮最多只需要按下一次,多按抵消。

当press作用于inp上时,效果就是对应位模2加(异或),那么每一个点作为一个未知数,他的上下左右的值会决定他的值。

你可能感兴趣的:(POJ 1222 高斯消元法解开关问题)