题目链接:http://poj.org/problem?id=1222
题意:就是给你一个初始矩阵(里面每个元素代表一个开关),改变一个开关就可以使得在其上、下、左、右的开关的状态都改变。问若使得所有开关均关闭(开关开为1,关为0),则需要改变哪些开关,并给出要改变的开关的矩阵图,里面的元素为1的表示要改变的开关,为0的表示不要变的开关。
思路:一共30盏灯,每盏灯的方程为 x(i*6+j)+x((i-1)*6+j)+x((i+1)*6+j)+x(i*6+j-1)+x(i*6+j+1)=b(mod 2)。我们知道每盏灯最后状态有本身以及上下左右的5盏灯决定,5盏灯的异或值就是最终的状态,只要求解这个模2方程即可。
code:
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 7 const int MAXN = 40; 8 //有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1,分别为0到var 9 int equ, var; 10 int a[MAXN][MAXN]; //增广矩阵 11 int x[MAXN]; //解集 12 int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用) 13 int free_num;//自由变元的个数 14 15 //返回值为-1表示无解,为0是唯一解,否则返回自由变元个数 16 int Gauss() { 17 int max_r, col, k; 18 free_num = 0; 19 for (k = 0, col = 0; k <equ&& col <var; k++, col++) { 20 max_r = k; 21 for (int i = k + 1; i<equ; i++) { 22 if (abs(a[i][col]) > abs(a[max_r][col])) 23 max_r = i; 24 } 25 if (a[max_r][col] == 0) { 26 k--; 27 free_x[free_num++] = col;//这个是自由变元 28 continue; 29 } 30 if (max_r != k) { 31 for (int j = col; j < var + 1; j++) 32 swap(a[k][j], a[max_r][j]); 33 } 34 for (int i = k + 1; i<equ; i++) { 35 if (a[i][col] != 0) { 36 for (int j = col; j < var + 1; j++) 37 a[i][j] ^= a[k][j]; 38 } 39 } 40 } 41 for (int i = k; i<equ; i++) 42 if (a[i][col] != 0) 43 return -1;//无解 44 if (k <var) return var - k;//自由变元个数 45 //唯一解,回代 46 for (int i = var - 1; i >= 0; i--) { 47 x[i] = a[i][var]; 48 for (int j = i + 1; j <var; j++) 49 x[i] ^= (a[i][j] && x[j]); 50 } 51 return 0; 52 } 53 54 int t[MAXN][MAXN]; 55 int dir[5][2] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } }; 56 57 void init() { 58 memset(t, 0, sizeof(t)); 59 for (int i = 0; i < 5; ++i) { 60 for (int j = 0; j < 6; ++j) { 61 for (int k = 0; k < 5; ++k) { 62 int a = i + dir[k][0]; 63 int b = j + dir[k][1]; 64 if (a >= 0 && b >= 0 && a < 5 && b < 6) { 65 t[6 * i + j][6 * a + b] = 1; 66 } 67 } 68 } 69 } 70 } 71 72 int main() 73 { 74 init(); 75 int T; 76 scanf("%d", &T); 77 for (int cas = 1; cas <= T; ++cas) { 78 memcpy(a, t, sizeof(a)); 79 for (int i = 0; i < 30; ++i) { 80 scanf("%d", &a[i][30]); 81 } 82 printf("PUZZLE #%d ", cas); 83 equ = 30; 84 var = 30; 85 if (Gauss() == 0) { 86 for (int i = 0; i < 30; ++i) { 87 if (i % 6 == 5) { 88 printf("%d ", x[i]); 89 } 90 else { 91 printf("%d ", x[i]); 92 } 93 } 94 } 95 } 96 return 0; 97 }