任意门: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

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 (不记顺序) 

题意概括:

如题。

解题思路:

根据开关之间的关系可以构造一个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:

 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int MAXN = ;
int N, cnt; int a[MAXN][MAXN]; //增广矩阵
int x[MAXN]; //解集
bool freeX[MAXN]; //标记自由元
int free_num; //自由元个数
int st[MAXN]; //记录初始状态
int ed[MAXN]; //记录最终状态 int Gauss(int equ, int var)
{
int maxRow, col, k;
free_num = ;
for(k = , col = ; k < equ && col < var; k++, col++){
maxRow = k;
for(int i = k+; i < equ; i++){ //寻找当前列绝对值最大的一行
if(abs(a[i][col]) > abs(a[maxRow][col])){
maxRow = i;
}
}
if(a[maxRow][col] == ){ //表示当前列绝对值最大的已经是0了,说明该列下面的全部都是0
k--;
freeX[free_num++] = col;
continue;
}
if(maxRow != k){ //绝对值最大的一行与当前行交换
for(int j = col; j < var+; j++){
swap(a[k][j] , a[maxRow][j]);
}
}
for(int i = k+; 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 -; if(k < var){
return var-k; //自由元的个数
}
//唯一解,回代
for(int i = var-; i >= ; i--){
x[i] = a[i][var];
for(int j = i+; j < var; j++){
x[i] ^= (a[i][j] && x[j]);
}
}
return ;
} int main()
{
int T_case;
int u, v;
scanf("%d", &T_case);
while(T_case--){
scanf("%d", &N);
for(int i = ; i < N; i++){
scanf("%d", &st[i]);
}
for(int i = ; i < N; i++){
scanf("%d", &ed[i]);
}
memset(a, , sizeof(a));
memset(x, , sizeof(x));
//构造增广矩阵
for(int i = ; i < N; i++){ //本开关肯定对本开关有影响
a[i][i] = ;
} while(~scanf("%d%d", &u, &v) && (u+v)){ //构造对除自身外开关的影响,自身是系数也是未知量
a[v-][u-] = ;
}
for(int i = ; i < N; i++){ //结果
a[i][N] = st[i]^ed[i]; //这里异或相当于对2取模运算
}
int ans = Gauss(N, N);
if(ans == -) printf("Oh,it's impossible~!!\n"); //无解
else printf("%d\n", <<ans); //2的ans次方,因为有ans个自由元
}
return ;
}

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. linux 拓展之linux纯命令行界面变为图形界面

    使用版本为6.x 1, 连接网络  没网络就下载不了哦 2,设置下yum源,我本机原来的yum源是网易的但是我用不了,我设置阿里云可以下载, 你们有这问题的可以试试    3, yum groupin ...

  2. 【Tensorflow】 Object_detection之liunx服务器安装部署步骤记录

    环境:centos7+anaconda python3.6 步骤: 1.下载Models cd 到预存放目录下,执行: git clone https://github.com/tensorflow/ ...

  3. Oracle 客户端、服务器、数据库、数据库对象(表、视图等)的关系

    1.数据库服务器 所谓数据库服务器,只是在机器上安装了一个数据库管理软件,这个软件可以管理多个数据库.一般开发人员会针对每一个应用创建一个数据库 2.单实例数据库模式下的数据库服务器.数据库.数据库实 ...

  4. UI特效资料-----ShaderWeaver

    主页:www.shaderweaver.com教程:www.shaderweaver.com/tutorials.html 1.一款插件,挺强大的 ShaderWeaver使用教程-基本操作介绍 ht ...

  5. 【学习】Unity手游之路<十二>手游资源热更新策略探讨

    http://blog.csdn.net/janeky/article/details/17666409 =============================================== ...

  6. vscode设置语言

     按 ctrl+shift+p   中文设置成英文输入 “配置语言”  打开locale.json 设置 "locale":"en" 英文设置成中文输入 &qu ...

  7. webpack缓存

    缓存 缓存如何工作 1.当缓存客户端需要访问数据时,它首先检查缓存.当在缓存中找到所请求的数据时,它被称为缓存命中. 2.如果在缓存中找不到请求的数据 , 称为缓存未命中的情况,它将从主存储器中提取并 ...

  8. vue——介绍和使用

    一.vue介绍 vue官网说:Vue.js(读音 /vjuː/,类似于 view) 是一套构建用户界面的渐进式的JavaScript框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计. ...

  9. JavaScript(Two)

    innerHtml xx.innerHtml 读取元素内的所有Html内容 xx.innerHtml = 新的值 替换元素内的所有Html内容 JS中不予许出现"-"; font- ...

  10. 【Linux】GDB程序调试

    一.GDB简介 GDB是GNU发布的一款功能强大的程序调试工具.GDB主要完成下面三个方面的功能: 启动被调试程序. 让被调试的程序在指定的位置停住. 当程序被停住时,可以检查程序状态(如变量值) 二 ...