开关问题
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 6455 | Accepted: 2463 |
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 (不记顺序)
Source
这到题目是高斯消元法的典型应用。
将将所有开关之间的关系当做系数,而对于开关的操作则作用为变量。
这样就形成了系数矩阵和变量矩阵。需要注意的是系数矩阵中每一行中的值a[i][j]表示的是j对i是否有影响。
代码:
Memory: 148 KB | Time: 0 MS | |
Language: C++ | Result: Accepted | |
Public: | No Yes |
Select All
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<vector> #include<map> #include<iostream> using namespace std; const int maxn=60; int a[maxn][maxn]; int x[maxn]; int free_x[maxn]; int gauss(int equ,int var) { int i,j,k,max_r,col; for(int i=0;i<=var;i++) { x[i]=0; free_x[i]=1; } col=0; for(k=0;k<equ&&col<var;k++,col++) { max_r=k; for(i=k+1;i<equ;i++) { if(abs(a[i][col])>abs(a[max_r][col])) max_r=i; } if(max_r!=k) { for(j=k;j<var+1;j++) swap(a[k][j],a[max_r][j]); } if(a[k][col]==0) { k--; continue; } for(i=k+1;i<equ;i++) { if(a[i][col]!=0) { for(j=col;j<var+1;j++) a[i][j]^=a[k][j]; } } } for(i=k;i<equ;i++) { if(a[i][col]!=0) return -1; } return var-k; } int start[maxn]; int end[maxn]; int main() { int n; int s,e; int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&start[i]); } for(int i=0;i<n;i++) { scanf("%d",&end[i]); } memset(a,0,sizeof(a)); while(scanf("%d%d",&s,&e)) { if(s==0&&e==0) break; a[e-1][s-1]=1; } for(int i=0;i<n;i++) a[i][i]=1; for(int i=0;i<n;i++) a[i][n]=start[i]^end[i]; int ans=gauss(n,n); if(ans==-1) printf("Oh,it‘s impossible~!!\n"); else printf("%d\n",1<<ans); } return 0; }
时间: 2024-10-14 08:28:13