[POJ1222]EXTENDED LIGHTS OUT(高斯消元,异或方程组)

题目链接:http://poj.org/problem?id=1222

题意:开关是四连通的,每按一个就会翻转自己以及附近的四个格(假如有)。问需要翻转几个,使他们都变成关。

把每一个灯看作一个未知量,可以有30个未知量,给每一个未知量从0~29编号,再列30个方程,每一个方程中描述每一个灯被翻转后其相邻等的状态变化,倒着考虑,把全关状态翻成当前状态就行了。

转移矩阵是这样的,很好理解。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 33;
 5 int equ, var;
 6 int a[maxn][maxn];
 7 int x[maxn];
 8 int free_x[maxn];
 9 int free_num;
10 
11 int gauss() {
12     int max_r, col, k;
13     free_num = 0;
14     for(k = 0, col = 0; k < equ && col < var; k++, col++) {
15         max_r = k;
16         for(int i = k + 1; i < equ; i++) {
17             if(abs(a[i][col]) > abs(a[max_r][col]))
18                 max_r = i;
19         }
20         if(a[max_r][col] == 0) {
21             k--;
22             free_x[free_num++] = col;
23             continue;
24         }
25         if(max_r != k) {
26             for(int j = col; j < var + 1; j++)
27                 swap(a[k][j], a[max_r][j]);
28         }
29         for(int i = k + 1; i < equ; i++) {
30             if(a[i][col] != 0) {
31                 for(int j = col; j < var + 1; j++) {
32                     a[i][j] ^= a[k][j];
33                 }
34             }
35         }
36     }
37     for(int i = k; i < equ; i++) {
38         if(a[i][col] != 0)
39             return -1;
40     }
41     if(k < var)
42         return var - k;
43     for(int i = var - 1; i >= 0; i--) {
44         x[i] = a[i][var];
45         for(int j = i + 1; j < var; j++) {
46             x[i] ^= (a[i][j] & x[j]);
47         }
48     }
49     return 0;
50 }
51 
52 int main() {
53     // freopen("in", "r", stdin);
54     equ = 30, var = 30;
55     int T, _ = 1;
56     scanf("%d", &T);
57     while(T--) {
58         memset(a, 0, sizeof(a));
59         memset(x, 0, sizeof(x));
60         memset(free_x, 0, sizeof(free_x));
61         for(int i = 0; i < 30; i++) {
62             scanf("%d", &a[i][var]);
63         }
64         for(int i = 0; i < 30; i++) {
65             a[i][i] = 1;
66             if(i % 6 != 0) a[i-1][i] = 1;
67             if(i % 6 != 5) a[i+1][i] = 1;
68             if(i > 5) a[i-6][i] = 1;
69             if(i < 24) a[i+6][i] = 1;
70         }
71         int v = gauss();
72         int cnt = 0;
73         printf("PUZZLE #%d
", _++);
74         for(int i = 0; i < 5; i++) {
75             for(int j = 0; j < 6; j++) {
76                 printf("%d ", x[cnt++]);
77             }
78             printf("
");
79         }
80     }
81     return 0;
82 }
原文地址:https://www.cnblogs.com/kirai/p/6137951.html