任意门:http://poj.org/problem?id=1830

开关问题

Time Limit: 1000MS

Memory Limit: 30000K

Total Submissions: 10742

Accepted: 4314

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

  1. 2
  2. 3
  3. 0 0 0
  4. 1 1 1
  5. 1 2
  6. 1 3
  7. 2 1
  8. 2 3
  9. 3 1
  10. 3 2
  11. 0 0
  12. 3
  13. 0 0 0
  14. 1 0 1
  15. 1 2
  16. 2 1
  17. 0 0

Sample Output

  1. 4
  2. Oh,it's impossible~!!

Hint

第一组数据的说明: 
一共以下四种方法: 
操作开关1 
操作开关2 
操作开关3 
操作开关1、2、3 (不记顺序) 

题意概括:

如题。

解题思路:

根据开关之间的关系可以构造一个0,1矩阵,然后通过求解这个矩阵,相加模2(即异或操作),求解线性方程组。

一个自由元即产生 2 种可能性,假设最后解的方程组存在ans个自由元 ,方案数就是 2 的 ans 次幂;

如何构造这样一个0,1增广矩阵呢?

设方程个数为 equ 个, 未知数个数为 var 个,我们最终构造出来的是一个 equ*(var+1)的0,1矩阵。

最后一列 a [ i ][ var + 1 ] 很容易 就是 初始状态 st [ i ] ^ 最终状态 ed [ i ];

而前面的系数矩阵呢?

其实是一个 N*N 的矩阵,可以把开关之间的关系理解成图的边,这个系数矩阵就是这个图的邻接矩阵。

构造出了增广矩阵,接下来的就是交给高斯消元去求解这个方程组了。

Ac code:

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <cmath>
  6. #include <map>
  7. #define LL long long
  8. #define INF 0x3f3f3f3f
  9. using namespace std;
  10. const int MAXN = ;
  11. int N, cnt;
  12.  
  13. int a[MAXN][MAXN]; //增广矩阵
  14. int x[MAXN]; //解集
  15. bool freeX[MAXN]; //标记自由元
  16. int free_num; //自由元个数
  17. int st[MAXN]; //记录初始状态
  18. int ed[MAXN]; //记录最终状态
  19.  
  20. int Gauss(int equ, int var)
  21. {
  22. int maxRow, col, k;
  23. free_num = ;
  24. for(k = , col = ; k < equ && col < var; k++, col++){
  25. maxRow = k;
  26. for(int i = k+; i < equ; i++){ //寻找当前列绝对值最大的一行
  27. if(abs(a[i][col]) > abs(a[maxRow][col])){
  28. maxRow = i;
  29. }
  30. }
  31. if(a[maxRow][col] == ){ //表示当前列绝对值最大的已经是0了,说明该列下面的全部都是0
  32. k--;
  33. freeX[free_num++] = col;
  34. continue;
  35. }
  36. if(maxRow != k){ //绝对值最大的一行与当前行交换
  37. for(int j = col; j < var+; j++){
  38. swap(a[k][j] , a[maxRow][j]);
  39. }
  40. }
  41. for(int i = k+; i < equ; i++){ //以绝对值最大的一行为标准对其他行进行消元
  42. if(a[i][col] != ){
  43. for(int j = col; j < var+; j++){
  44. a[i][j] ^= a[k][j];
  45. }
  46. }
  47. }
  48. }
  49. for(int i = k; i < equ; i++) //判断是否无解
  50. if(a[i][col] != )
  51. return -;
  52.  
  53. if(k < var){
  54. return var-k; //自由元的个数
  55. }
  56. //唯一解,回代
  57. for(int i = var-; i >= ; i--){
  58. x[i] = a[i][var];
  59. for(int j = i+; j < var; j++){
  60. x[i] ^= (a[i][j] && x[j]);
  61. }
  62. }
  63. return ;
  64. }
  65.  
  66. int main()
  67. {
  68. int T_case;
  69. int u, v;
  70. scanf("%d", &T_case);
  71. while(T_case--){
  72. scanf("%d", &N);
  73. for(int i = ; i < N; i++){
  74. scanf("%d", &st[i]);
  75. }
  76. for(int i = ; i < N; i++){
  77. scanf("%d", &ed[i]);
  78. }
  79. memset(a, , sizeof(a));
  80. memset(x, , sizeof(x));
  81. //构造增广矩阵
  82. for(int i = ; i < N; i++){ //本开关肯定对本开关有影响
  83. a[i][i] = ;
  84. }
  85.  
  86. while(~scanf("%d%d", &u, &v) && (u+v)){ //构造对除自身外开关的影响,自身是系数也是未知量
  87. a[v-][u-] = ;
  88. }
  89. for(int i = ; i < N; i++){ //结果
  90. a[i][N] = st[i]^ed[i]; //这里异或相当于对2取模运算
  91. }
  92. int ans = Gauss(N, N);
  93. if(ans == -) printf("Oh,it's impossible~!!\n"); //无解
  94. else printf("%d\n", <<ans); //2的ans次方,因为有ans个自由元
  95. }
  96. return ;
  97. }

POJ 1830 开关问题 【01矩阵 高斯消元】的更多相关文章

  1. POJ 1222 EXTENDED LIGHTS OUT(高斯消元解异或方程组)

    EXTENDED LIGHTS OUT Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 10835   Accepted: 6 ...

  2. POJ 1222 EXTENDED LIGHTS OUT(高斯消元)

    [题目链接] http://poj.org/problem?id=1222 [题目大意] 给出一个6*5的矩阵,由0和1构成,要求将其全部变成0,每个格子和周围的四个格子联动,就是说,如果一个格子变了 ...

  3. POJ 1222 EXTENDED LIGHTS OUT(高斯消元)题解

    题意:5*6的格子,你翻一个地方,那么这个地方和上下左右的格子都会翻面,要求把所有为1的格子翻成0,输出一个5*6的矩阵,把要翻的赋值1,不翻的0,每个格子只翻1次 思路:poj 1222 高斯消元详 ...

  4. POJ 1681 Painter's Problem(高斯消元+枚举自由变元)

    http://poj.org/problem?id=1681 题意:有一块只有黄白颜色的n*n的板子,每次刷一块格子时,上下左右都会改变颜色,求最少刷几次可以使得全部变成黄色. 思路: 这道题目也就是 ...

  5. POJ 1222 EXTENDED LIGHTS OUT(高斯消元解XOR方程组)

    http://poj.org/problem?id=1222 题意:现在有5*6的开关,1表示亮,0表示灭,按下一个开关后,它上下左右的灯泡会改变亮灭状态,要怎么按使得灯泡全部处于灭状态,输出方案,1 ...

  6. BZOJ3503:[CQOI2014]和谐矩阵(高斯消元,bitset)

    Description 我们称一个由0和1组成的矩阵是和谐的,当且仅当每个元素都有偶数个相邻的1.一个元素相邻的元素包括它本 身,及他上下左右的4个元素(如果存在). 给定矩阵的行数和列数,请计算并输 ...

  7. POJ 1681 Painter's Problem 【高斯消元 二进制枚举】

    任意门:http://poj.org/problem?id=1681 Painter's Problem Time Limit: 1000MS   Memory Limit: 10000K Total ...

  8. poj1830开关问题——异或高斯消元

    题目:http://poj.org/problem?id=1830 根据题意,构造出n元方程组: a(1,1)x1 ^ a(1,2)x2 ^ a(1,3)x3 ... a(1,n)xn = st1 ^ ...

  9. poj 1681 Painter&#39;s Problem(高斯消元)

    id=1681">http://poj.org/problem? id=1681 求最少经过的步数使得输入的矩阵全变为y. 思路:高斯消元求出自由变元.然后枚举自由变元,求出最优值. ...

随机推荐

  1. selenium原理和尝试

    引用文章:https://www.cnblogs.com/Albert-Lee/p/6238866.html Selenium是一个自动化测试框架.因为它能够模拟人工操作,比如能在浏览器中点击按钮.在 ...

  2. linux 命令之重定向

    linux 重定向及部分命令 一,重定向讲解: 1> 标准输出重定向 覆盖原有内容 慎用!!!!!! 1>> 标准输出追加重定向 追加内容 2> 错误输出重定向 只输出错误信息 ...

  3. IE Error: '__doPostBack' is undefined 问题解决

    突然遇到个很奇怪的BUG,翻页控件,其他浏览器一切正常,IE无法翻页,会提示 '__doPostBack' is undefined 后来搜索发现: [原文發表地址] Bug and Fix: ASP ...

  4. bootstrap的datepicker使用(1.将默认的英文设置为中文2.选择日月年的时候记录之前的操作)

    参考网页    bootstrap datepicker 属性设置 以及方法和事件 1.如何将bootstrap的datepicker默认的英文设置为中文 第一步,新建一个js文件(bootstrap ...

  5. 深度学习(五)基于tensorflow实现简单卷积神经网络Lenet5

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/8954892.html 参考博客:https://blog.csdn.net/u01287127 ...

  6. git读书笔记以及使用技巧

    [添加文件] git add  把文件修改添加到暂存区    git commit -m '' 把暂存区的所有内容提交到当前分支 [查看历史]    git log 查看提交历史 git log -- ...

  7. js跑步算法

    <!DOCTYPE html> <html> <head> <title>JavaScript</title> <style> ...

  8. ASP.NET安全[开发ASP.NET MVC应用程序时值得注意的安全问题](转)

    概述 安全在web领域是一个永远都不会过时的话题,今天我们就来看一看一些在开发ASP.NET MVC应用程序时一些值得我们注意的安全问题.本篇主要包括以下几个内容 : 认证 授权 XSS跨站脚本攻击 ...

  9. 从零开始的全栈工程师——html篇1

    全栈工程师也可以叫web 前端 H5主要是网站 app 小程序 公众号这一块 HTML篇 html(超文本标记语言,标记通用标记语言下的一个应用.) “超文本”就是指页面内可以包含图片.链接,甚至音乐 ...

  10. jQuery之设置元素内容(移动和复制元素,使用append(),appendTo()方法)

    jQuery之设置元素内容(移动和复制元素,使用append(),appendTo()方法) ---------- 如果想把内容添加到现有内容末尾,可以利用append()命令.append()命令语 ...