UVALive 5070 Awkward Lights

来源:互联网 发布:重低音增强软件 编辑:程序博客网 时间:2024/06/07 00:45

关键词:判断异或方程组是否有解、求异或方程组的解数
题意:已知n*m矩阵填上0/1,当将其中某个数反转时,与其哈密顿距离为d的点数字也将反转,判断最终能否全部反转为0
解法:该图是一种状态,全0是另一种状态,状态中的每个分量(矩阵中每个位置的数)受与它距离为d的位置及其本身反转次数的异或组合影响,因此xi=1表示第i个位置反转,xi=0表示不反转。可以列出n*m个异或方程。求异或方程组需要用到gauss消元

拓展:求异或方程组的总解数,即每个位置最多反转1次,求总的反转方案数(反转次序不同算作同一反转方案)
gauss函数中返回行数i,ans=(1<<(n-r))

#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>#include<map>#include<vector>#include<queue>#include<stack>#define ll long longusing namespace std;const int maxn =25+10;typedef int Matrix[maxn*maxn][maxn*maxn];int m,n,d;int a[maxn][maxn];//原始矩阵Matrix A;int row,col;//增广矩阵及其行列大小;void build(){    row=col=n*m;    memset(A,0,sizeof(A));    for(int i=0;i<n;i++){        for(int j=0;j<m;j++){            A[i*m+j][i*m+j]=1;            for(int ii=0;ii<n;ii++){                for(int jj=0;jj<m;jj++){                    if(abs(i-ii)+abs(j-jj)==d) A[i*m+j][ii*m+jj]=1;                }            }            if(a[i][j]) A[i*m+j][col]=1;        }    }}bool gauss(Matrix A,int m,int n){//m行n+1列增广矩阵    int i=0,j=0,r;    while(i<m&&j<n){        r=i;        for(int ii=i;ii<m;ii++) if(A[ii][j]) { r=ii;break; }        if(A[r][j]){            if(r!=i) for(int jj=0;jj<=n;jj++) swap(A[i][jj],A[r][jj]);            for(int ii=i+1;ii<m;ii++){                if(A[ii][j])                    for(int jj=j;jj<=n;jj++){                        A[ii][jj]^=A[i][jj];                    }            }            i++;        }        j++;    }    for(int ii=i;ii<m;ii++){        if(A[ii][n]) return false;    }    return true;}int main(){    //freopen("a.txt","r",stdin);    while(scanf("%d%d%d",&m,&n,&d)!=EOF){        if(!m||!n||!d) break;        for(int i=0;i<n;i++)            for(int j=0;j<m;j++)                scanf("%d",&a[i][j]);        build();        if(gauss(A,row,col)) printf("1\n");        else printf("0\n");    }    return 0;}
0 0