• poj1753 (高斯消元法求异或方程组)


    题目链接:http://poj.org/problem?id=1753

    题意:经典开关问题,和poj1222一样,进行两次高斯消元即可,只用初始化的时候改一下初始状态。可能存在无解或多解的情况,多解要枚举自由变元的所有状态。

    AC代码:

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    
    const int maxn=20;
    const int inf=0x3f3f3f3f;
    int mp[5][5],a[maxn][maxn],x[maxn],equ,var,free_x[maxn];
    char s[5];
    
    void init(int p){
        memset(a,0,sizeof(a));
        for(int i=0;i<4;++i){
            for(int j=0;j<4;++j){
                int t=i*4+j;
                a[t][16]=p^mp[i][j];
                a[t][t]=1;
                if(i>0) a[t][(i-1)*4+j]=1;
                if(i<3) a[t][(i+1)*4+j]=1;
                if(j>0) a[t][i*4+j-1]=1;
                if(j<3) a[t][i*4+j+1]=1;
            }
        }
    }
    
    int Gauss(){
        int r=0,cnt=0;
        for(int c=0;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(Maxr!=r){
                for(int i=c;i<var+1;++i)
                    swap(a[r][i],a[Maxr][i]);
            }
            if(!a[r][c]){
                --r;
                free_x[cnt++]=c;
                continue;
            }
            for(int i=r+1;i<equ;++i){
                if(!a[i][c]) continue;
                for(int j=c;j<var+1;++j)
                    a[i][j]^=a[r][j];
            }
        }
        for(int i=r;i<equ;++i)
            if(a[i][var])
                return -1;
        return var-r;
    }
    
    int solve(int t){
        int ret=inf;
        for(int i=0;i<(1<<t);++i){
            int cnt=0;
            memset(x,0,sizeof(x));
            for(int j=0;j<t;++j){
                if((i>>j)&1){
                    ++cnt;
                    x[free_x[j]]=1;
                }
            }
            for(int j=var-t-1;j>=0;--j){
                int tmp=a[j][var],tp,ok=1;
                for(int k=j;k<var;++k){
                    if(!a[j][k]) continue;
                    if(ok){
                        ok=0;
                        tp=k;
                    }
                    else{
                        tmp^=x[k];
                    }
                }
                x[tp]=tmp;
                cnt+=x[tp];
            }
            ret=min(ret,cnt);
        }
        return ret;
    }
    
    int main(){
        equ=var=16;
        for(int i=0;i<4;++i){
            scanf("%s",s);
            for(int j=0;j<4;++j)
                if(s[j]=='b') mp[i][j]=0;
                else mp[i][j]=1;
        }
        init(0);
        int t1,t2,t3,t4;
        t1=Gauss();
        if(t1!=-1) t2=solve(t1);
        init(1);
        t3=Gauss();
        if(t3!=-1) t4=solve(t3);
        if(t1==-1&&t3==-1)
            printf("Impossible
    ");
        else
            printf("%d
    ",min(t2,t4));
        return 0;
    }
  • 相关阅读:
    iOS开发-文件管理(一)
    浅析栈区和堆区内存分配的区别
    浅谈Block传值-匿名函数(代码块)
    cell的各种使用和赋值 总结
    类方法和对象方法的区别
    属性传值 ,代理传值,单例
    类目,延展,协议
    任意点 并查集
    Codeforces 145E. Lucky Queries 线段树
    Codeforces 103B. Cthulhu 并查集运用
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11772530.html
Copyright © 2020-2023  润新知