zoukankan      html  css  js  c++  java
  • poj1222(高斯消元法解异或方程组+开关问题)

    题目链接:https://vjudge.net/problem/POJ-1222

    题意:给定一个5×6的01矩阵,改变一个点的状态时它上下左右包括它自己的状态都会翻转,因为翻转2次等价与没有翻转,那么每个点要么不翻转,要么翻转一次,求最终要怎样翻转可以使得矩阵全0。

    思路:

      做法1(枚举): 因为数据小,可以枚举第一行的所有可能,共1<<6种,之后的每一行都根据上一行决定,然后通过判断最后一行是否满足条件来判断这种方案是否可行。

      做法2(高斯消元法): 为了说的清楚,现在假定矩阵为2×3,比如为,现在要达到的目标状态是:

        现在要求6个灯的状态,相当于6个变量。另外有6个方程,分别表示6个点最终的状态。

        比如,对于第0个灯,能影响到它的就是第0、1、3盏灯,因此它的方程是: (1*x0) ^ (1*x1) ^ (0*x2) ^ (1*x3) ^ (0*x4) ^ (0*x5) =0,(式子右边的0表示第0盏灯最开始的状态)。

        同理第1盏灯的方程即为:(1*x0) ^ (1*x1) ^ (1*x2) ^ (0*x3) ^ (1*x4) ^ (0*x5) =1。

        因此可以列出6个方程,然后用高斯消元法来求解,异或方程组的处理和普通线性方程组是一样的。

        对于题目就是5×6=30个方程,30个变量分别表示30盏灯的状态。

    AC代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    using namespace std;
    
    const int maxn=40;
    int T,cas,a[maxn][maxn],ans[maxn];
    
    void init(){
        memset(a,0,sizeof(a));
        memset(ans,0,sizeof(ans));
        for(int i=0;i<5;++i){
            for(int j=0;j<6;++j){
                int t=i*6+j;
                a[t][t]=1;
                if(i>0) a[t][t-6]=1;
                if(i<4) a[t][t+6]=1;
                if(j>0) a[t][t-1]=1;
                if(j<5) a[t][t+1]=1;
            }
        }
    }
    
    void Gauss(int equ,int var){
        int r=0,c=0;
        for(;r<equ&&c<var;++r,++c){
            int Maxr=r;
            for(int i=r+1;i<equ;++i)
                if(abs(a[i][c])>abs(a[Maxr][c]))
                    Maxr=i;
            if(a[Maxr][c]==0){
                --r;
                continue;
            }
            if(Maxr!=r){
                for(int i=c;i<=var;++i)
                    swap(a[r][i],a[Maxr][i]);
            }
            for(int i=r+1;i<equ;++i){
                if(a[i][c]==0) continue;
                for(int j=c;j<=var;++j)
                    a[i][j]^=a[r][j];
            }
        }
        for(int i=var-1;i>=0;--i){
            ans[i]=a[i][var];
            for(int j=i+1;j<equ;++j)
                ans[i]^=(a[i][j]&ans[j]);
        }
    }
    
    int main(){
        scanf("%d",&T);
        while(T--){
            init();
            for(int i=0;i<30;++i)
                scanf("%d",&a[i][30]);
            Gauss(30,30);
            printf("PUZZLE #%d
    ",++cas);
            for(int i=0;i<5;++i){
                for(int j=0;j<6;++j){
                    printf("%d",ans[i*6+j]);
                    if(j!=5) printf(" ");
                }
                printf("
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    【★】KMP算法完整教程
    【★】KMP算法完整教程
    算法之【牛顿迭代法】
    算法之【牛顿迭代法】
    【★】Web精彩实战之
    【★】Web精彩实战之
    ★RFC标准库_目录链接
    ★RFC标准库_目录链接
    ★教师工资为什么这么低?/整理
    ★教师工资为什么这么低?/整理
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11769946.html
Copyright © 2011-2022 走看看