UVA 1560 - Extended Lights Out
题意:给定一个矩阵,1代表开着灯,0代表关灯,没按一个开关,周围4个位置都会变化,问一个按的方法使得所有灯都变暗
思路:两种做法:
1、枚举递推
这个比较简单,就枚举第一行,然后递推过去,每次如果上一行是亮灯,则下一行开关必须按下去
2、高斯消元,
这个做法比较屌一些,每个位置对应上下左右中5个位置可以列出一个异或表达式,然后30个位置对应30个异或表达式,利用高斯消元法就能求出每个位置的解了
代码:
高斯消元法:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int d[5][2] = {{0, 0}, {0, 1}, {0, -1}, {1, 0}, {-1, 0}};
int t, a[31][31], out[6][6];
void back() {
for (int i = 29; i >= 0; i--)
out[i / 6][i % 6] = a[i][30];
}
void guess() {
for (int i = 0; i < 30; i++) {
int k = i;
for (; k < 30; k++)
if (a[k][i]) break;
for (int j = 0; j <= 30; j++)
swap(a[i][j], a[k][j]);
for (int j = 0; j < 30; j++) {
if (i == j) continue;
if (a[j][i]) {
for (int k = i; k <= 30; k++)
a[j][k] ^= a[i][k];
}
}
}
back();
}
int main() {
int cas = 0;
scanf("%d", &t);
while (t--) {
memset(a, 0, sizeof(a));
for (int i = 0; i < 30; i++)
scanf("%d", &a[i][30]);
for (int i = 0; i < 30; i++) {
int x = i / 6, y = i % 6;
for (int j = 0; j < 5; j++) {
int xx = x + d[j][0];
int yy = y + d[j][1];
if (xx < 0 || xx >= 5 || yy < 0 || yy >= 6) continue;
a[i][xx * 6 + yy] = 1;
}
}
guess();
printf("PUZZLE #%d\n", ++cas);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++)
printf("%d ", out[i][j]);
printf("%d\n", out[i][5]);
}
}
return 0;
}
枚举递推:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int d[5][2] = {{0, 0}, {1, 0}, {-1, 0}, {0, 1}, {0, -1}};
const int N = 6;
int t, g[N][N], tmp[N][N], out[N][N];
bool judge(int s) {
memset(out, 0, sizeof(out));
for (int i = 0; i < 5; i++)
for (int j = 0; j < 6; j++)
tmp[i][j] = g[i][j];
for (int i = 0; i < 6; i++) {
if (s&(1<<i)) {
out[0][i] = 1;
for (int j = 0; j < 5; j++) {
int xx = d[j][0];
int yy = i + d[j][1];
if (xx < 0 || yy < 0 || xx >= 5 || yy >= 6) continue;
tmp[xx][yy] = (!tmp[xx][yy]);
}
}
}
for (int i = 1; i < 5; i++) {
for (int j = 0; j < 6; j++) {
if (tmp[i - 1][j]) {
out[i][j] = 1;
for (int k = 0; k < 5; k++) {
int xx = i + d[k][0];
int yy = j + d[k][1];
if (xx < 0 || yy < 0 || xx >= 5 || yy >= 6) continue;
tmp[xx][yy] = (!tmp[xx][yy]);
}
}
}
}
for (int i = 0; i < 6; i++)
if (tmp[4][i]) return false;
return true;
}
void solve() {
for (int i = 0; i < (1<<6); i++)
if (judge(i)) return;
}
int main() {
int cas = 0;
scanf("%d", &t);
while (t--) {
for (int i = 0; i < 5; i++)
for (int j = 0; j < 6; j++)
scanf("%d", &g[i][j]);
solve();
printf("PUZZLE #%d\n", ++cas);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++)
printf("%d ", out[i][j]);
printf("%d\n", out[i][5]);
}
}
return 0;
}