Poj 1830 高斯消元

开关问题
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 5418 Accepted: 2022

Description

有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。你的任务是,计算有多少种可以达到指定状态的方法。(不计开关操作的顺序)

Input

输入第一行有一个数K,表示以下有K组测试数据。 
每组测试数据的格式如下: 
第一行 一个数N(0 < N < 29) 
第二行 N个0或者1的数,表示开始时N个开关状态。 
第三行 N个0或者1的数,表示操作结束后N个开关的状态。 
接下来 每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化。每组数据以 0 0 结束。 

Output

如果有可行方法,输出总数,否则输出“Oh,it's impossible~!!” 不包括引号

Sample Input

2

3

0 0 0

1 1 1

1 2

1 3

2 1

2 3

3 1

3 2

0 0

3

0 0 0

1 0 1

1 2

2 1

0 0

Sample Output

4

Oh,it's impossible~!!

Hint

第一组数据的说明: 
一共以下四种方法: 
操作开关1 
操作开关2 
操作开关3 
操作开关1、2、3 (不记顺序) 
 
 1 /*************************************************************************  2  > File Name: Poj_1830.cpp  3  > Author: Stomach_ache  4  > Mail: [email protected]  5  > Created Time: 2014年07月10日 星期四 09时57分40秒  6  > Propose:  7  ************************************************************************/

 8 

 9 #include <cmath>

10 #include <string>

11 #include <cstdio>

12 #include <vector>

13 #include <fstream>

14 #include <cstring>

15 #include <iostream>

16 #include <algorithm>

17 using namespace std; 18 

19 const int MAX_N = 35; 20 const double EPS = 1E-8; 21 

22 int A[MAX_N][MAX_N], S[MAX_N], E[MAX_N]; 23 

24 int gauss_jordan(int n, int m) { 25       int i, j; //i维护矩阵的秩 26       for (i =0, j = 0; i < n && j < m; i++, j++) { 27           int pivot = i; 28         for (int k = i+1; k < n; k++) { 29               if (abs(A[k][j] > abs(A[pivot][j]))) pivot = k; 30  } 31         if (abs(A[pivot][j]) < EPS) { 32               i--; 33             continue; 34         }// 放弃这一行, 直接处理下一行

35         if (pivot != i) for (int k = 0; k <= m; k++) swap(A[i][k], A[pivot][k]); 36         

37         // 把正在处理的未知数系数变为1

38         for (int k = i+1; k <= m; k++) A[i][k] /= A[i][j]; 39         for (int r = 0; r < n; r++) if (i != r) { 40               for (int k = j+1; k <= m; k++) 41                   // A[j][k] -= A[j][i] * A[i][k];

42                   A[r][k] = (A[r][k] - A[r][j] * A[i][k] + 2) % 2; 43  } 44  } 45     //无解

46     for (int k = i; k < n; k++) if (A[k][m] != 0) return -1; 47     if (i == n) return 1; 48     //自由变元的个数为 n - i,每个变元有两种状态

49     return 1<<(n-i); 50 } 51 

52 int main(void) { 53     int K, N; 54       scanf("%d", &K); 55     while (K--) { 56           scanf("%d", &N); 57         for (int i  = 0; i < N; i++) scanf("%d", S+i); 58         for (int i  = 0; i < N; i++) scanf("%d", E+i); 59         int i, j; 60         memset(A, 0, sizeof(A)); 61         while (scanf("%d %d", &i, &j) && i+j) A[j-1][i-1] = 1; 62         // 构造增广矩阵

63         for (int i = 0; i < N; i++) { 64               A[i][N] = S[i] ^ E[i]; 65             A[i][i] = 1; 66  } 67         int ans = gauss_jordan(N, N); 68         if (ans == -1) puts("Oh,it's impossible~!!"); 69         else printf("%d\n", ans); 70  } 71 

72     return 0; 73 }

 

你可能感兴趣的:(poj)