POJ 1830 开关问题 【01矩阵 高斯消元】
任意门:http://poj.org/problem?id=1830
开关问题
Time Limit: 1000MS |
Memory Limit: 30000K |
|
Total Submissions: 10742 |
Accepted: 4314 |
Description
Input
每组测试数据的格式如下:
第一行 一个数N(0 < N < 29)
第二行 N个0或者1的数,表示开始时N个开关状态。
第三行 N个0或者1的数,表示操作结束后N个开关的状态。
接下来 每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化。每组数据以 0 0 结束。
Output
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矩阵 高斯消元】的更多相关文章
- POJ 1222 EXTENDED LIGHTS OUT(高斯消元解异或方程组)
EXTENDED LIGHTS OUT Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 10835 Accepted: 6 ...
- POJ 1222 EXTENDED LIGHTS OUT(高斯消元)
[题目链接] http://poj.org/problem?id=1222 [题目大意] 给出一个6*5的矩阵,由0和1构成,要求将其全部变成0,每个格子和周围的四个格子联动,就是说,如果一个格子变了 ...
- POJ 1222 EXTENDED LIGHTS OUT(高斯消元)题解
题意:5*6的格子,你翻一个地方,那么这个地方和上下左右的格子都会翻面,要求把所有为1的格子翻成0,输出一个5*6的矩阵,把要翻的赋值1,不翻的0,每个格子只翻1次 思路:poj 1222 高斯消元详 ...
- POJ 1681 Painter's Problem(高斯消元+枚举自由变元)
http://poj.org/problem?id=1681 题意:有一块只有黄白颜色的n*n的板子,每次刷一块格子时,上下左右都会改变颜色,求最少刷几次可以使得全部变成黄色. 思路: 这道题目也就是 ...
- POJ 1222 EXTENDED LIGHTS OUT(高斯消元解XOR方程组)
http://poj.org/problem?id=1222 题意:现在有5*6的开关,1表示亮,0表示灭,按下一个开关后,它上下左右的灯泡会改变亮灭状态,要怎么按使得灯泡全部处于灭状态,输出方案,1 ...
- BZOJ3503:[CQOI2014]和谐矩阵(高斯消元,bitset)
Description 我们称一个由0和1组成的矩阵是和谐的,当且仅当每个元素都有偶数个相邻的1.一个元素相邻的元素包括它本 身,及他上下左右的4个元素(如果存在). 给定矩阵的行数和列数,请计算并输 ...
- POJ 1681 Painter's Problem 【高斯消元 二进制枚举】
任意门:http://poj.org/problem?id=1681 Painter's Problem Time Limit: 1000MS Memory Limit: 10000K Total ...
- 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 ^ ...
- poj 1681 Painter's Problem(高斯消元)
id=1681">http://poj.org/problem? id=1681 求最少经过的步数使得输入的矩阵全变为y. 思路:高斯消元求出自由变元.然后枚举自由变元,求出最优值. ...
随机推荐
- Angular4+NodeJs+MySQL 入门-01
有一定的后台开发经验ES6语法.后台没有用框架来,纯自己写.会sql语句 安装NodeJS的安装 从网上下载 https://nodejs.org/en/ 选择自己,我用的是最新版本 Angular ...
- git使用问题及解决方法
1. 设置pull默认rebasegit config --global pull.rebase true 2. 问题解决:Unlink of file '.git/objects/pack/pack ...
- AI从入门到放弃:CNN的导火索,用MLP做图像分类识别?
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:郑善友 腾讯MIG后台开发工程师 导语:在没有CNN以及更先进的神经网络的时代,朴素的想法是用多层感知机(MLP)做图片分类的识别:但 ...
- 关于EF执行返回表的存储过程
1.关于EF执行返回表的存储过程 不知道为什么EF生成的存储过程方法会报错,以下方法可以使用,call是MySQL执行存储过程的命令 [HttpGet] public HttpResponseMess ...
- vs文件属性(复制到输出目录)是什么意思
右击项目里的文件,选择属性(F4)会有复制到输出目录的选项. 它提供三项选择,如图: 如果选择始终复制或如果较新则复制会在该程序集的bin目录下生成该文件,如图:
- .net比较两个时间的大小,不含日期,精确到分
解决方案: 1.将要比较的两个时间转成DateTime类型: DateTime date1 = DateTime.Parse("8:00"); DateTime date2 = D ...
- 重构指南 - 封装集合(Encapsulate Collection)
封装就是将相关的方法或者属性抽象成为一个对象. 封装的意义: 对外隐藏内部实现,接口不变,内部实现自由修改. 只返回需要的数据和方法. 提供一种方式防止数据被修改. 更好的代码复用. 当一个类的属性类 ...
- HDU 5215 Cycle(dfs判环)
题意 题目链接 \(T\)组数据,给出\(n\)个点\(m\)条边的无向图,问是否存在一个奇环/偶环 Sol 奇环比较好判断吧,直接判是否是二分图就行了.. 偶环看起来很显然就是如果dfs到一个和他颜 ...
- IntelliJ IDEA热部署教程,只要两步!
一.开启idea自动build功能1.File -> Settings -> Build,Execution,Deployment -> Compiler -> Build p ...
- 03_CronTrigger
[Cron表达式] Quartz使用类似于Linux下的Cron表达式定义的时间规则,Cron表达式由6到7个空格分隔的时间字段组成. [ 字符说明 ] * :可以用在所有字段中,表示对应时间域内的每 ...