首页 > 代码库 > UVA 1560 - Extended Lights Out(高斯消元)
UVA 1560 - Extended Lights Out(高斯消元)
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]; 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; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。