POJ -- 1830 高斯消元

题目链接: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 查看本文章

猜你喜欢

转载自blog.csdn.net/water_zero_saber/article/details/79857707