[zz]高斯消元法解01异或方程组

//原文链接:https://blog.csdn.net/qq547276542/article/details/49806363
const int maxn=50;
//有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1
int equ,var;
int a[maxn][maxn]; //增广矩阵
int x[maxn];  //解集
int free_x[maxn];
int free_num;
void init(){
    memset(a,0,sizeof(a));
    memset(x,0,sizeof(x));
    equ=30,var=30;
}
//返回-1表示无解,0代表是唯一解,并生成解集x[],否则返回自由变元个数
int Gauss(){
    int max_r,col,k;
    free_num=0;
    for(k=0,col=0;k<equ&&col<var;k++,col++)
	{
        max_r=k;
        for(int i=k+1;i<equ;i++){
            if(abs(a[i][col])>abs(a[max_r][col]))
                max_r=i;
        }
        if(a[max_r][col]==0)
		{
            k--;
            free_x[free_num++]=col;
            continue;
        }
        if(max_r!=k)
		{
            for(int j=col;j<var+1;j++)
                swap(a[k][j],a[max_r][j]);
        }
        for(int i=k+1;i<equ;i++)
		{
            if(a[i][col]!=0)
			{
                for(int j=col;j<var+1;j++)
                    a[i][j]^=a[k][j];
            }
        }
    }
    for(int i=k;i<equ;i++)
        if(a[i][col]!=0)
            return -1;  //无解
    if(k<var) return var-k;  //解不唯一,返回解个数
    //解唯一,生成解集
    for(int i=var-1;i>=0;i--){
        x[i]=a[i][var];
        for(int j=i+1;j<var;j++)
            x[i]^=(a[i][j]&&x[j]);
    }
    return 0;
}

  

POJ 1222(高斯消元法)

题意:5*6矩阵中有30个灯,操作一个灯,周围的上下左右四个灯会发生相应变化
即由灭变亮,由亮变灭,如何操作使灯全灭?
分析:这个问题是很经典的高斯消元问题。同一个按钮最多只能被按一次,
因为按两次跟没有按是一样的效果。那么
对于每一个灯,用1表示按,0表示没有按,那么每个灯的状态的取值只能是0或1。
列出30个方程,30个变元,高斯消元解出即可,因为解只能是0或者1,所以方程组是一定有解。

#include<queue>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<set>
using namespace std;
const int maxn=50;
//有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1
int equ,var;
int a[maxn][maxn]; //增广矩阵
int x[maxn];  //解集
int free_x[maxn];
int free_num;
void init(){
    memset(a,0,sizeof(a));
    memset(x,0,sizeof(x));
    equ=30,var=30;
}
//返回-1表示无解,0代表是唯一解,并生成解集x[],否则返回自由变元个数
int Gauss(){
    int max_r,col,k;
    free_num=0;
    for(k=0,col=0;k<equ&&col<var;k++,col++){
        max_r=k;
        for(int i=k+1;i<equ;i++){
            if(abs(a[i][col])>abs(a[max_r][col]))
                max_r=i;
        }
        if(a[max_r][col]==0){
            k--;
            free_x[free_num++]=col;
            continue;
        }
        if(max_r!=k){
            for(int j=col;j<var+1;j++)
                swap(a[k][j],a[max_r][j]);
        }
        for(int i=k+1;i<equ;i++){
            if(a[i][col]!=0){
                for(int j=col;j<var+1;j++)
                    a[i][j]^=a[k][j];
            }
        }
    }
    for(int i=k;i<equ;i++)
        if(a[i][col]!=0)
            return -1;  //无解
    if(k<var) return var-k;  //解不唯一,返回解个数
    //解唯一,生成解集
    for(int i=var-1;i>=0;i--){
        x[i]=a[i][var];
        for(int j=i+1;j<var;j++)
            x[i]^=(a[i][j]&&x[j]);
    }
    return 0;
}
int G[maxn][maxn];
int main() {
    freopen("in.txt","r",stdin);
    int T;
    cin>>T;
    int now=0;
    while(T--){
        for(int i=0;i<5;i++){
            for(int j=0;j<6;j++)
                scanf("%d",&G[i][j]);
        }
        init();
        for(int i=0;i<5;i++){
            for(int j=0;j<6;j++){
                int t=i*6+j;
                a[t][t]=1;
                a[t][30]=G[i][j];
                if(i>0)a[t][(i-1)*6+j]=1;
                if(i<4)a[t][(i+1)*6+j]=1;
                if(j>0)a[t][i*6+j-1]=1;
                if(j<5)a[t][i*6+j+1]=1;
            }
        }
        int k=Gauss();
        printf("PUZZLE #%d
",++now);
        for(int i=0;i<5;i++){
            for(int j=0;j<6;j++){
                if(j!=0)cout<<" ";
                cout<<x[i*6+j];
            }
            cout<<endl;
        }
    }
    return 0;
}

 

相关习题:
https://blog.csdn.net/u011815404/article/details/88890702
[Noip模拟题]遇见
Usaco Light
环上的高斯消元

原文地址:https://www.cnblogs.com/cutemush/p/12283202.html