首页 > 代码库 > Poj 1830 高斯消元
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
230 0 01 1 11 21 32 12 33 13 20 030 0 01 0 11 22 10 0
Sample Output
4Oh,it‘s impossible~!!
Hint
第一组数据的说明:
一共以下四种方法:
操作开关1
操作开关2
操作开关3
操作开关1、2、3 (不记顺序)
1 /************************************************************************* 2 > File Name: Poj_1830.cpp 3 > Author: Stomach_ache 4 > Mail: sudaweitong@gmail.com 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 // 把正在处理的未知数系数变为138 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 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。