POJ 1830 开关问题

最近入手一本神书 上交教练编的,一共四本,我买的是全模版那套。

翻开一看第2节就是高斯消元,正好我不会,就拿题来练手。

 

昂。。。打开题一看,蒙的一B啊。。这和高斯消元有毛关系啊。。。

仔细想想,如果x1动了一次,那么x2也会动一次,

那么对于x2来说,它动的次数=sum(x1+x2+....xn),

这题求的是自由元的个数,所以与sum是多少无关,所以令sum=u[i]^v[i]就行了,

 

代码中r是矩阵的秩,n-r就是自由元的个数了。每一个自由元有2种出现的方式,结果就是1<<n-r。

对于r以下的行,必定全是0,那么如果a[i][n]!=0 必然出现矛盾,于是判定无解。

 

#include<stdio.h>
#include<math.h>
#include<iostream>
#define eps 1e-7
using namespace std;
double a[110][110],as[110];
int n,u[110],v[110];
bool l[110];
int gauss(){
	int i,j,k,r=0;
	double tmp;
	for(i=0;i<n;i++)
		l[i]=0;
	for(i=0;i<n;i++){
	    for(j=r;j<n;j++)
	        if(fabs(a[j][i])>eps){
				for(k=i;k<=n;k++)
				    swap(a[j][k],a[r][k]);
				break;
			}
		if(fabs(a[r][i])<eps)continue;
		for(j=0;j<n;j++)
		    if(j!=r&&fabs(a[j][i])>eps){
				tmp=a[j][i]/a[r][i];
				for(k=i;k<=n;k++)
				    a[j][k]-=tmp*a[r][k];
			}
		l[i]=1;r++;
	}
	for(i=0;i<n;i++)if(l[i])
	    for(j=0;j<n;j++)
	        if(fabs(a[j][i])>eps)
	            as[i]=a[j][n]/a[j][i];
	for(i=r;i<n;i++)if(fabs(a[i][n])>eps)return -1;
	return 1<<n-r;
}
int main(){
	int i,j,x,y,cs;
	scanf("%d",&cs);
	while(cs--){
		scanf("%d",&n);
		for(i=0;i<=n;i++)
		    for(j=0;j<=n;j++)
		        a[i][j]=0;
		for(i=0;i<n;i++)
		    scanf("%d",&u[i]);
		for(i=0;i<n;i++){
		    scanf("%d",&v[i]);
		    a[i][n]=u[i]^v[i];
		    a[i][i]=1;
		}
		while(scanf("%d%d",&i,&j),i||j)
			a[j-1][i-1]=1;
		x=gauss();
		if(x==-1)puts("Oh,it's impossible~!!");
		else    printf("%d\n",x);
	}
	return 0;
}


 

总感觉用int不稳妥。。虽然这题都是1 0,貌似不存在小数的情况,但我还是用double做了。。

你可能感兴趣的:(POJ 1830 开关问题)