zoj 3155 Street Lamp 高斯消元 异或方程组 求方案数

题目链接:http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3155

题意:给出一张图有灯泡的连接关系和初始灯泡状态,相邻的灯泡如果相连则可以相互影响,求使所有灯泡最后都关闭的不同操作的情况数。

和poj1222差不多,不过这题求的是方案数。

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

 

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