题目链接: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; }