高斯消元枚举自由元——poj1222

来源:互联网 发布:股票大数据分析软件 编辑:程序博客网 时间:2024/06/06 04:08
#include<stdio.h>#include<algorithm>#include<iostream>#include<string.h>using namespace std;int a[230][230],x[230],free_x[230],free_num,r,c;int Gauss(){    int k,col,max_r,i,j;    for(free_num=k=col=0;k<r&&col<c;col++)  //枚举行,列从0开始    {        max_r=k;        for(i=k+1;i<r;i++)            if(abs(a[i][col])>abs(a[max_r][col]) )max_r=i;   //找到这一列里面绝对值最大的        if(!a[max_r][col])        {            free_x[free_num++]=col;            continue;   //最大的都是0,那么这一列不用考虑了        }        if(max_r!=k)            for(i=col;i<=c;i++) swap(a[max_r][i],a[k][i]);  //否则交换        for(i=k+1;i<r;i++)            if(a[i][col]!=0)                for(j=col;j<=c;j++) a[i][j]^=a[k][j];        k++;    }    for(i=k;i<r;i++)        if(a[i][col]) return -1;    if(k<c) return c-k;    for(i=c-1;i>=0;i--)    {        x[i]=a[i][c];        for(j=i+1;j<c;j++)            x[i]^=(a[i][j]&&x[j]);    }    return 0;}int main(){    int i,j,T,n,v,ans;    char s[16];    scanf("%d",&T);    while(T--)    {        memset(a,0,sizeof(a));        memset(x,0,sizeof(x));        scanf("%d",&n);        for(i=0;i<n;i++)        {            scanf("%s",s);            for(j=0;j<n;j++)                if(s[j]=='y') a[i*n+j][n*n]=0;                else a[i*n+j][n*n]=1;        }        c=r=n*n;        for(i=0;i<n;i++)            for(j=0;j<n;j++)            {               v=i*n+j;               a[v][v]=1;               if(i>0) a[v-n][v]=1;               if(i<n-1) a[v+n][v]=1;               if(j>0) a[v-1][v]=1;               if(j<n-1) a[v+1][v]=1;            }        v=Gauss();        if(v<0)        {            printf("inf\n");            continue;        }        if(v==0)        {            ans=0;            for(i=0;i<n*n;i++)                if(x[i]) ans++;            printf("%d\n",ans);        }        else        {            ans=0x7fffffff;            int tot=1<<v;            for(i=0;i<tot;i++)            {                int cnt=0;                for(j=0;j<v;j++)                    if(i&(1<<j))                    {                        cnt++;                        x[free_x[j]]=1;                    }                    else x[free_x[j]]=0;                for(j=c-v-1;j>=0;j--)                {                    int p;                    for(p=j;p<c;p++)                        if(a[j][p]) break;                    x[p]=a[j][c];                    for(int l=p+1;l<c;l++)                        if(a[j][l]) x[p]^=x[l];                    if(x[p]) cnt++;                }                ans=min(ans,cnt);            }            printf("%d\n",ans);        }    }}

0 0
原创粉丝点击