您的位置:首页 > 其它

poj1830 开关问题 【Gauss消元】

2013-04-11 12:01 405 查看
http://poj.org/problem?id=1830

题目大意:有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。你的任务是,计算有多少种可以达到指定状态的方法。(不计开关操作的顺序)

  将方程组做成矩阵形式,然后利用三种初等矩阵变换,得到上三角矩阵,最后回代得到解集。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 41;
struct Matrix {
int n , m;
ll a

;
Matrix() {}
Matrix(int _n,int _m):n(_n),m(_m){};
void intput() {
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&a[i][j]);
}
void clear() {
memset(a,0,sizeof(a));
}
Matrix operator + (const Matrix &b) {
Matrix tmp = Matrix(n,m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
tmp.a[i][j] = a[i][j] + b.a[i][j];
return tmp;
}
Matrix operator - (const Matrix &b) {
Matrix tmp = Matrix(n,m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
tmp.a[i][j] = a[i][j] - b.a[i][j];
return tmp;
}
Matrix operator * (const Matrix &b) {
Matrix tmp = Matrix(n,b.m);
for(int i=0;i<n;i++)
for(int j=0;j<b.m;j++)
tmp.a[i][j] = 0;
for(int i=0;i<n;i++)
for(int k=0;k<m;k++)
if(a[i][k])
for(int j=0;j<b.m;j++)
tmp.a[i][j] += a[i][k]*b.a[k][j];
return tmp;
}
};

Matrix operator ^ (Matrix a , int p) {
Matrix ret = Matrix(a.n,a.m);
for(int i=0;i<a.n;i++)
for(int j=0;j<a.m;j++)
ret.a[i][j] = (i == j ? 1 : 0);
while(p) {
if(p%2) ret = ret * a;
a = a * a;
p /= 2;
}
return ret;
}
/*
Matrix mi(Matrix a , int p) {
Matrix tmp = Matrix(a.n,a.m);
for(int i=0;i<a.n;i++)
for(int j=0;j<a.m;j++)
if(i==j) tmp.a[i][j]=1;
else tmp.a[i][j]=0;
if(p == 0) return tmp;
if(p == 1) return a;
if(p % 2) tmp = a;
Matrix tt = mi(a , p/2);
return tt * tt * tmp;
}*/
Matrix A;
int Gauss(Matrix A,int r,int c) {
int i,j,k,col;
for(k=col=0;k<r&&col<c;k++,col++) {
int kk = k;
for(i=k+1;i<r;i++)
if(A.a[i][col]>A.a[kk][col])
kk = i;
if(kk != k)
for(j=col;j<c+1;j++)
swap(A.a[k][j],A.a[kk][j]);
if(A.a[k][col] == 0) {
k --; continue;
}
for(i=k+1;i<r;i++)
if(A.a[i][col])
for(j=col;j<c+1;j++)
A.a[i][j] ^= A.a[k][j];
}
for(i=k;i<r;i++)
if(A.a[i][col])
return -1;
int ans = 1;
for(i=0;i<c-k;i++) ans *= 2;
return ans;
}
int main() {
int T , n;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
A = Matrix(n+1,n+1);
A.clear();
for(int i=0;i<n;i++) scanf("%d",&A.a[i]
);
for(int i=0;i<n;i++) {
int tmp;
scanf("%d",&tmp);
A.a[i]
^= tmp;
}
int x , y;
while(scanf("%d%d",&x,&y) && x+y) {
x --; y --;
A.a[y][x] = 1;
}
for(int i=0;i<n;i++) A.a[i][i] = 1;
int ans = Gauss(A,n,n);
if(ans == -1) puts("Oh,it's impossible~!!");
else printf("%d\n" , ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: