poj 1830 开关问题 高斯消元

题意:给你n个开关,给定开关的初状态和要达到的末状态,并给出i j 代表操作i也会影响j。

如果有可行方法,输出方法总数。否则输出“Oh,it's impossible~!!”。

这样我们就可以很快根据给定的数据建立一个方程组高斯消元求解。

我们求得的自由变元个数为k,可行方法自然就是(1<<k)。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int a[33][33],st[33],to[33];
int n;
void debug()
{
	int i,j;
	puts("debug");
	for(i = 0;i < n; i++)
	{
		for(j = 0;j < n+1;j ++)
			printf("%d ", a[i][j]);
		puts("");
	}
	puts("end");
}
void gauss()
{
	int i,j;
	int row = 0, col = 0;
//	debug();
	for( ; row < n && col < n ; row++, col++)
	{
		int maxr = row;
		for(i = row+1;i < n; i++)
			if(a[i][col])
				maxr = i;
		if(!a[maxr][col])
		{
			row--;
			continue;
		}
		if(row != maxr)
			for(i = col;i < n+1;i ++)
				swap(a[maxr][i] , a[row][i]);
		for(i = row+1;i < n; i++)
			if(a[i][col])
				for(j = col;j < n+1; j++)
					a[i][j] ^= a[row][j];
	}
//	debug();
	for(i = row;i < n; i++)
		if(a[i][n])
		{
			puts("Oh,it's impossible~!!");
			return ;
		}
	printf("%d\n", 1<<(n-row));
}
int main()
{
	int i,j,t;
	scanf("%d", &t);
	while(t--)
	{
		memset(a,0,sizeof(a));
		scanf("%d", &n);
		for(i = 0;i < n; i++)
			scanf("%d", &st[i]);
		for(i = 0;i < n; i++)
			scanf("%d", &to[i]);
		while(scanf("%d%d", &i, &j) && i)
			a[j-1][i-1] = 1;
		for(i = 0;i < n ;i++)
			a[i][i] = 1;
		for(i = 0;i < n; i++)
			if(st[i] != to[i])
				a[i][n] = 1;
		gauss();
	}
	return 0;
}


你可能感兴趣的:(poj,高斯消元)