题意:给定一个矩阵,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]; for (int j = 0; j < i; j++) { if (a[j][i]) a[j][30] ^= 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 = i + 1; j < 30; j++) { 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; }
UVA 1560 - Extended Lights Out(高斯消元),布布扣,bubuko.com
UVA 1560 - Extended Lights Out(高斯消元)
原文:http://blog.csdn.net/accelerator_/article/details/38024673