Language: Default 开关问题
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+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; }
版权声明:本文为博主原创文章,转载请注明出处。
时间: 2025-01-05 12:33:14