poj 1830 开关问题 (高斯消元)

题意:

给出一些开关互相影响的关系,问从开关的初始状态到结束状态有多少种变换的方法。

题解:

对于每个开关可能会受1....i某写开关的影响,因此对于开关i列出一个列向量,列向量每个元素只有1或0,表示某个开关是否影响这个i开关,这样就n个开关组合成一个矩阵,结束状态也是一个列向量,这样就可以用高斯消元求解解的个数。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define B(x) (1<<(x))
typedef long long ll;
const int oo=0x3f3f3f3f;
const ll OO=1LL<<61;
const int MOD=10007;
const int maxn=1000;
int maze[maxn][maxn];
int x[maxn];
int s[maxn],e[maxn];

int Gauss(int n,int m){
    int r,c;
    for(r=0,c=0;r<n&&c<m;r++,c++){
        int id=r;
        for(int i=r+1;i<n;i++){
            if(maze[i][c]>maze[id][c]){
                id=i;
            }
        }
        if(id!=r){
            for(int j=c;j<=m;j++){
                swap(maze[id][j],maze[r][j]);
            }
        }
        if(maze[r][c]==0){
            r--;
            continue;
        }
        for(int i=r+1;i<n;i++){
            if(maze[i][c]!=0){
                for(int j=c;j<=m;j++){
                    maze[i][j]^=maze[r][j];
                }
            }
        }
    }

    for(int i=r;i<n;i++){
        if(maze[i][c]!=0)return -1;
    }

    return B(c-r);
}

int main(){

//#define ON 1
#ifdef ON
    freopen("E:\\read.txt","r",stdin);
#endif // ON

    int T,n,a,b;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        memset(maze,0,sizeof maze);
        for(int i=0;i<n;i++)scanf("%d",&s[i]);
        for(int i=0;i<n;i++)scanf("%d",&e[i]);
        for(int i=0;i<n;i++){
            maze[i][n]=s[i]^e[i];
            maze[i][i]=1;
        }
        while(scanf("%d %d",&a,&b)){
            if(a==0&&b==0)break;
            maze[b-1][a-1]=1;
        }
        int ans=Gauss(n,n);
        if(ans==-1) printf("Oh,it's impossible~!!\n");
        else printf("%d\n",ans);
    }
    return 0;
}
/**

*/




你可能感兴趣的:(poj 1830 开关问题 (高斯消元))