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\n");
    else
        printf("%d\n",min(t2,t4));
    return 0;
}

 

posted @ 2019-10-31 17:22  Frank__Chen  阅读(315)  评论(0编辑  收藏  举报