#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加(异或),那么每一个点作为一个未知数,他的上下左右的值会决定他的值。