POJ 1681 高斯消元 枚举自由变元

题目和poj1222差不多,但是解法有一定区别,1222只要求出任意一解,而本题需要求出最少翻转次数。所以需要枚举自由变元,变元数量为n,则枚举的次数为1<<n次

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=500;
char s[maxn][maxn];
int a[maxn][maxn],x[maxn],fre[maxn];
const int INF=1e9;

void debug(int n)
{
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
            printf("%d ",a[i][j]);
        printf(" %d\n",a[i][n]);
    }
}

void init(int n)
{
    int dx[]= {0,0,-1,0,1};
    int dy[]= {0,-1,0,1,0};
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            for(int k=0; k<5; k++)
            {
                int x=i+dx[k];
                int y=j+dy[k];
                if(x>=0 && x<n && y>=0 && y<n)
                    a[i*n+j][x*n+y]=1;
            }
        }
    }
}

int Guass(int equ,int var)
{
    int k,col,num=0;
    for(k=0,col=0; k<equ && col<var; k++,col++)
    {
        int rr=k;
        for(int i=k; i<equ; i++)
            if(a[i][col]!=0)
            {
                rr=i;
                break;
            }
        if(rr!=k)
            for(int j=col; j<var+1; j++)
                swap(a[k][j],a[rr][j]);
        if(a[k][col]==0)
        {
            k--;
            fre[num++]=col;
            continue;
        }
        for(int i=k+1; i<equ; i++)
        {
            if(a[i][col]==0) continue;
            for(int j=col; j<var+1; j++)
                a[i][j]^=a[k][j];
        }
    }
    //debug(equ);
    for(int i=k; i<equ; i++)
        if(a[i][var]!=0) return -1;
    int sta=1<<(var-k);//自由变元有var-k个
    int res=INF;
    for(int i=0; i<sta; i++) //枚举所有变元
    {
        int cnt=0;
        int index=i;
        for(int j=0; j<num; j++)
        {
            x[fre[j]]=(index&1);
            if(x[fre[j]]) cnt++;
            index>>=1;
        }
        for(int row=k-1; row>=0; row--)
        {
            x[row]=a[row][var];
            for(col=row+1; col<var; col++)
                x[row]^=(a[row][col]*x[col]);
            if(x[row])cnt++;
        }
        res=min(cnt,res);
    }
    return res;
}

int main()
{
    //freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(a,0,sizeof(a));
        memset(fre,1,sizeof(fre));
        int n;
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            scanf("%s",s[i]);
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
                a[i*n+j][n*n]=(s[i][j]=='y'? 0:1);
        init(n);
        int ans=Guass(n*n,n*n);
        if(ans==-1)
        {
            printf("inf\n");
            continue;
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2017-05-21 21:37  Pacify  阅读(429)  评论(0编辑  收藏  举报