poj1222 EXTENDED LIGHTS OUT 高斯消元解异或方程组 模板

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

题意:给出一个5*6的图,每个灯泡有一个初始状态,1表示亮,0表示灭。每对一个灯泡操作时,会影响周围的灯泡改变亮灭,问如何操作可以使得所有灯泡都关掉。

思路:因为每盏灯,如果操作两次就相当于没有操作,所以相当于(操作次数)%2,即异或操作。

考虑一个2*3的图,最后需要的状态是 :,如果初始状态为:。对这两个矩阵的每个数字做异或操作可以得到线性方程组每个方程的答案。

总共6盏灯,0-5。那么可以列出6个方程。

对于第0盏灯,会影响到它的是第0, 1, 3盏灯,因此可以列出方程1*x0 + 1*x1 + 0*x2 + 1*x3 + 0*x4 + 0*x5= 0。

对于第1盏灯,会影响到它的是第0, 1, 2,4盏灯,因此可以列出方程1*x0 + 1*x1 + 1*x2 + 0*x3 + 1*x4 + 0*x5 = 1。

对于第2盏灯,会影响到它的是第1, 2, 5盏灯,因此可以列出方程0*x0 + 1*x1 + 1*x2 + 0*x3 + 0*x4 + 1*x5 = 0。

.....

所以最后可以列出增广矩阵:

然后用高斯消元求这个矩阵的解就可以了。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <cmath>
 5 using namespace std;
 6 #define maxn 8
 7 int a[maxn*maxn][maxn*maxn];
 8 int x[maxn*maxn];
 9 int mp[maxn][maxn];
10 void init()
11 {
12     memset(a, 0, sizeof(a));
13     for(int i = 0; i < 5; i++)
14     {
15         for(int j = 0; j < 6; j++)
16         {
17             int pos = i*6+j;
18             a[pos][pos] = 1;
19             if(i > 0) a[pos][(i-1)*6+j] = 1;
20             if(i < 4) a[pos][(i+1)*6+j] = 1;
21             if(j > 0) a[pos][i*6+j-1] = 1;
22             if(j < 5) a[pos][i*6+j+1] = 1;
23         }
24     }
25 }
26 void Gauss(int n, int m)
27 {
28     memset(x, 0, sizeof(x));
29     int r, c;
30     for(r = 0, c = 0; r < n && c < m; r++, c++)
31     {
32         int max_r = r;
33         for(int i = r+1; i < n; i++)
34         {
35             if(fabs(a[i][c]) > fabs(a[max_r][c])) max_r = i;
36         }
37         if(a[max_r][c] == 0) {r--; continue;}
38         if(max_r != r)
39         {
40             for(int i = c; i < m+1; i++) swap(a[max_r][i], a[r][i]);
41         }
42         
43         for(int i = r+1; i < n; i++)
44         {
45             if(a[i][c] == 0) continue;
46             for(int j = c; j < m+1; j++) a[i][j] ^= a[r][j];
47         }
48     }
49     
50     for(int i = m-1; i >= 0; i--)
51     {
52         x[i] = a[i][m];
53         for(int j = i+1; j < m; j++)
54         {
55             x[i] ^= (a[i][j] && x[j]);
56         }
57     }
58 }
59 int main() 
60 {
61    // freopen("in.txt", "r", stdin);
62     int T;
63     scanf("%d", &T);
64     int cast = 0;
65     while(T--)
66     {
67         cast++;
68         init();
69         for(int i = 0; i < 5; i++)
70         {
71             for(int j = 0; j < 6; j++)
72             {
73                 scanf("%d", &a[i*6+j][30]);
74             }
75         }
76         Gauss(30, 30);
77         printf("PUZZLE #%d\n", cast);
78         for(int i = 0; i < 5; i++)
79         {
80             for(int j = 0; j < 6; j++)
81             {
82                 if(j == 0) printf("%d", x[i*6+j]);
83                 else printf(" %d", x[i*6+j]);
84             }
85             printf("\n");
86         }
87     }
88     return 0;
89 }

 

posted @ 2016-04-15 21:28  下周LGD该赢了吧  阅读(1483)  评论(0编辑  收藏  举报