POJ-1222 EXTENDED LIGHTS OUT(高斯消元)
2015-08-10 14:19
597 查看
题意:
给你一个5*6的矩阵,每个点上都有一个灯,按下f[i][j]的按钮,f[i][j]位置的灯的状态会改变,它上下左右的灯的状态也会改变(开变关,关变开)。
现在给出这个矩阵的初始状态,输出按下哪些按钮,使所有的灯都关闭。
做法:
利用高斯消元解异或方程组。
用x[i][j]表示第i行第j列的灯是否被按下
x[i][j] ^ x[i+1][j] ^ x[i-1][j] ^ x[i][j+1] ^ x[i][j-1]= f[i][j]
从给定的状态到全0的解=从全0状态到给定状态的解
用^和&&来代替实数高斯消元里的加减即可。
本题“认为”有唯一解就好了。
(注:引用了kuangbin的写法)
给你一个5*6的矩阵,每个点上都有一个灯,按下f[i][j]的按钮,f[i][j]位置的灯的状态会改变,它上下左右的灯的状态也会改变(开变关,关变开)。
现在给出这个矩阵的初始状态,输出按下哪些按钮,使所有的灯都关闭。
做法:
利用高斯消元解异或方程组。
用x[i][j]表示第i行第j列的灯是否被按下
x[i][j] ^ x[i+1][j] ^ x[i-1][j] ^ x[i][j+1] ^ x[i][j-1]= f[i][j]
从给定的状态到全0的解=从全0状态到给定状态的解
用^和&&来代替实数高斯消元里的加减即可。
本题“认为”有唯一解就好了。
(注:引用了kuangbin的写法)
#include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 50; //未知数数目 int equ, var; //equ个方程,var个变元 int a[MAXN][MAXN]; //行数为equ,0~var列为系数,var列为得数 int x[MAXN]; //解集 int free_num; //自由变元数量 int free_x[MAXN]; //自由变元,多解枚举时会用到 /******************************************************* * mod2高斯消元过程 * 返回-1无解,0惟一解,>0自由变元数目 *******************************************************/ int Gauss() { int maxr, col, i, j, k; free_num = 0; for (k = 0, col = 0; k<equ && col<var; k++, col++) { maxr = k; for (i = k + 1; i<equ; i++) { if (abs(a[i][col])>abs(a[maxr][col])) maxr = i; } if (a[maxr][col] == 0) { k--; free_x[free_num++] = col; //出现一个自由变元 continue; } if (maxr != k) { for (j = col; j<var + 1; j++) swap(a[k][j], a[maxr][j]); } for (i = k + 1; i<equ; i++) { if (a[i][col] != 0) { for (j = col; j<var + 1; j++) a[i][j] ^= a[k][j]; } } } for (i = k; i<equ; i++) if (a[i][col] != 0) return -1; //无解情况 if (k<var) return var - k; //多个自由变元 for (i = var - 1; i >= 0; i--) //惟一解,进行回代 { x[i] = a[i][var]; for (j = i + 1; j<var; j++) x[i] ^= (a[i][j] && x[j]); } return 0; } void work() { int i, j, k, t; memset(a, 0, sizeof(a)); memset(x, 0, sizeof(x)); equ = 30; var = 30; for (i = 0; i<5; i++) for (j = 0; j<6; j++) { t = i * 6 + j; a[t][t] = 1; //itself if (i > 0) a[(i - 1) * 6 + j][t] = 1; //top if (i < 4) a[(i + 1) * 6 + j][t] = 1; //bottom if (j > 0) a[i * 6 + j - 1] [t] = 1; //left if (j < 5) a[i * 6 + j + 1] [t] = 1; //right } for (i = 0; i < 30; i++) scanf("%d",&a[i][30]); Gauss(); for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) printf("%d ", x[6 * i + j]); printf("%d\n",x[6*i+5]); } } int main() { int i, T; scanf("%d", &T); for (i = 1; i <= T; i++) { printf("PUZZLE #%d\n", i); work(); } return 0; }
相关文章推荐
- CentOS 7 安装PostGIS
- Dijkstra(优先队列优化)
- ProGuard Version5.2(4.1)Manual-->Introduction
- ASP入门(三)-VBScript变量、运算符
- A Plug for UNIX
- 代码流程分析二:Settings-蓝牙分析-myDevice根preference分析
- 欢迎使用CSDN-markdown编辑器
- 题解分析及总结:经典逻辑面试题“假设有一个池塘,里面有无穷多的水,现有2个空水壶,如何使用少于15L的水,用2个水壶从池塘里取得3升水”
- 大数据学习之BigData常用算法和数据结构
- 安卓欢迎界面和activity之间的跳转问题
- Android/Kernel代码阅读工具之OpenGrok
- A Plug for UNIX 分类: POJ 图论 函数 2015-08-10 14:18 2人阅读 评论(0) 收藏
- 同时共用MOB公司的shareSDK和SMSSDK的冲突问题
- Linux/OS X下将Jar包转换成可直接执行文件(不用java -jar)
- 动画知识点汇总
- 设计模式--代理模式
- loadrunner的术语,分析等。破解
- 线段树之HDU3974 Assign the task
- UNITY3D学习笔记12
- opencv轮廓高级应用(轮廓匹配,几何直方图)