题目链接:http://poj.org/problem?id=1830
中文题意,我就不多说什么了,学习高斯消元时看到的这道题,其实一开始我还没看懂这题跟高斯消元有什么关系,emmm都怪我线代学的太差了.
这道题中,我们不妨设A[i][j] = 1表示第j灯可以影响到第i灯,若为0则表示无影响,显然A[i][i] = 1
又设X[i]代表第i个开关的操作状态(1位操作,0为不操作), S[i]为开始状态,E[i]为结束状态,则可列出N个方程:
( X[1] * A[i][1] + X[2] * A[i][2] + ... + X[n] * A[i][n] ) % 2 = (E[i] - S[i]);
看,是不是像线性方程组了呢?于是我们利用高斯消元,可以得到r个解,剩下的n-r个就是自由元,对于这些
自由元,我们可以随便的取1 or 0, 所以就有2^(n-r)种操作。
特殊的,如果某一行的系数全为0,而增广矩阵最后一列对应的行的值不为0,则表示无解。
AC代码如下:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int a[30][30], n, b[30];
int Guss()
{
int i, j, k, l;
for(i = j = 0; i < n && j < n; i++, j++){
k = i;
for(l = i+1; l < n; l++){
if(a[l][j] > a[k][j]) k = l;
}
if(k != i){
for(l = j; l <= n; l++)
swap(a[k][l], a[i][l]);
}
if(!a[i][j]){
i--;
continue;
}
for(l = i+1; l < n; l++){
if(a[l][j]){
for(int p = j; p <= n; p++)
a[l][p] ^= a[i][p];
}
}
}
for(l = i; l < n; l++){
if(a[l][n]) return -1;
}
if(i == n) return 1;
else return pow(2, n-i);
}
int main()
{
int T;
cin >> T;
while(T--){
memset(a, 0, sizeof(a));
scanf("%d", &n);
for(int i = 0; i < n; i++){
scanf("%d", &b[i]);
}
for(int i = 0; i < n; i++){
int tmp;
cin >> tmp;
a[i][n] = tmp^b[i];
a[i][i] = 1;
}
int p, q;
while(~scanf("%d %d", &p, &q)){
if(p == 0 && q == 0) break;
a[q-1][p-1] = 1;
}
int r = Guss();
if(r == -1) cout << "Oh,it's impossible~!!" << endl;
else cout << r << endl;
}
return 0;
}
扫描二维码关注公众号,回复:
2394567 查看本文章