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. 思路:高斯消元求出自由变元.然后枚举自由变元,求出最优值. ...
随机推荐
- Django From表单定制
参考文档: Forms The Forms API Working with forms 一.简单的Form表达定制 1)首先我们得定制Form表单类,下面我们创建一个简单的类: class Book ...
- ckeditor和ckfinder
ckeditor是一个所见即所得的富文本编辑器,用来代替drupal自带的编辑器. 但是从drupal.com下载的ckeditor模块本身没有实现功能,它指向了由cdn.ckeditor.com所提 ...
- JS正则表达式一些基本使用、验证、匹配、正则匹配时一个变量
js验证首位必须是字母 var str = "asfg"; /^[a-zA-Z].*/.test(str);//true是,false否 匹配所有空格 var str=" ...
- ObjectHeader、ObjectType和ObjectHook的学习
0x01 前言 之前研究RootKit技术,发现了对象钩子这个概念,一直不知道是什么,然后在网上搜,最先找到的是sudami的一篇文章,于是跟着大牛的脚步研究,其中也参考<内核情景分析>, ...
- could not find an installed version of gradle either in android studio
问题描述: 很多人在Ionic升级到3之后,无缘无故发现,当我们添加android平台后,build或者run的时候,命令行窗口给我们提示: 如果在Ionic2时add的android platfor ...
- JavaScript实现StringBuffer
function StringBuffer() { this._strings = new Array(); } StringBuffer.prototype.Append = function(_s ...
- C# 在窗体的子线程中创建新窗体
在子线程中如果简单的调用新窗体的话,新出来的窗体会直接一闪而过.没有停留.效果很差 具体解决方法 如下: 在母窗体中建立委托 public delegate void setShowChartForm ...
- scss-变量作用域
SCSS之所以便利,是因为它具有了编程语言的某些特性. 让原本规则刻板的CSS变的灵活起来,下面介绍一下SCSS中的作用域概念. 几乎所有编程语言都有作用域概念的涉及,原理大同小异,SCSS中的也是如 ...
- CSS3媒体查询总结
1.什么是媒体查询 媒体查询可以让我们根据设备显示器的特性(如视口宽度.屏幕比例.设备方向:横向或纵向)为其设定CSS样式,媒体查询由媒体类型和一个或多个检测媒体特性的条件表达式组成.媒体查询中可用于 ...
- Swiper双向轮播
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...