zoukankan      html  css  js  c++  java
  • [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
    环上的高斯消元

  • 相关阅读:
    BZOJ 3260: 跳 (组合恒等式)
    BZOJ 1924 [SDOI 2010] 所驼门王的宝藏 (优化建图+tarjan+最长链)
    BZOJ 3451Normal (点分治+FFT)
    BZOJ 2213: [Poi2011]Difference (DP)
    BZOJ 3251 树上三角形 (暴力)
    [HNOI2008]明明的烦恼
    HDU 1521 排列组合
    [HNOI2008]神奇的国度
    [HNOI2008]遥远的行星
    [HNOI2001]软件开发
  • 原文地址:https://www.cnblogs.com/cutemush/p/12283202.html
Copyright © 2011-2022 走看看