POJ 开关问题 1830【高斯消元求矩阵的秩】
Language:
开关问题
Description
有N个同样的开关。每一个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其它的与此开关相关联的开关也会对应地发生变化,即这些相联系的开关的状态假设原来为开就变为关,假设为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于随意一个开关,最多仅仅能进行一次开关操作。你的任务是,计算有多少种能够达到指定状态的方法。(不计开关操作的顺序)
Input
输入第一行有一个数K,表示下面有K组測试数据。
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+X=B 两边同一时候异或A就能够了。这样就能简单得到增广矩阵。
a[i][j]是j灯控制i灯。
记得把a[i][i]的情况加上,差点忽略这点,自己当然能够控制自己啊。
AC代码:
#include <stdio.h> #include <math.h> #include <vector> #include <queue> #include <string> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> #define MAXN 31 using namespace std; int equ,var; int a[MAXN][MAXN]; int Gauss() { int col=0; int k,max_r; for(k=0;col<var&&k<equ;k++,col++){ max_r=k; for(int i=k+1;i<equ;i++) if(abs(a[i][col])>abs(a[max_r][col])) max_r=i; if(max_r!=k){ for(int i=col;i<=var;i++) swap(a[k][i],a[max_r][i]); } if(!a[k][col]){ k--; continue; } for(int i=k+1;i<equ;i++) if(a[i][col]) for(int j=col;j<=var;j++) a[i][j]^=a[k][j]; } for(int i=k;i<equ;i++) if(a[i][col]) return -1; return var-k; } int main() { int T; scanf("%d",&T); while(T--){ memset(a,0,sizeof(a)); scanf("%d",&equ); var=equ; int b; for(int i=0;i<equ;i++){ //a[i][i]=1; scanf("%d",&b); a[i][var]=b; } for(int i=0;i<equ;i++){ scanf("%d",&b); a[i][var]^=b; } int I,J; while(scanf("%d%d",&I,&J),I!=0||J!=0){ a[J-1][I-1]=1; } for(int i=0;i<equ;i++) a[i][i]=1; int res=Gauss(); if(res<0)printf("Oh,it's impossible~!!\n"); else printf("%d\n",1<<res); } return 0; }