Description

Input
Output
Sample Input
2 3 yyy yyy yyy 5 wwwww wwwww wwwww wwwww wwwww
Sample Output
0 15
Source
高斯消元法解异或方程组.
得到的每个方程类似与mat[0][0]*x[0] ^ mat[0][1]^X[1] ^ .....^mat[0][var-1]*x[var-1] = b[0]
我们把矩阵的第i行上和第i个开关有关系的那些系数赋值为1,其他的为0,在最后一列放置那个开关的初态和末态的改变,得到增广矩阵,高消之后枚举自由变量找到最少操作数即可。
//高斯消元法解异或方程组,poj1681
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=300;
int x[maxn];//存最后的解
int mat[maxn][maxn];
int free_x[maxn];//存自由变元
int Gauss(int equ,int var)
{
int i,j,k;
int free_index,free_num;
int max_r,col,num;
col=0;
num=0;
for(k=0;k<equ && col<var;k++,col++)
{
max_r=k;//找到col列上绝对值最大的那行(k行的下面那些行)
for(i=k+1;i<equ;i++)
{
if(abs(mat[i][col]) > abs(mat[max_r][col]))
max_r=i;
}
if(max_r!=k)//找到后和第k行交换
{
for(j=k;j<var+1;j++)
swap(mat[k][j],mat[max_r][j]);
}
if(!mat[k][col])
{
k--;
//free_x[num++]=col;//如果第k行第col这个数为0,也就是系数为0,那他就是个自由变量
continue;
}
for(i=k+1;i<equ;i++)
{
if(mat[i][col])
{
for(j=col;j<var+1;j++)
mat[i][j]^=mat[k][j];//异或以后消去k+1行到最后一行的第col列的系数,形成上三角矩阵
}
}
}
for(i=k;i<equ;i++)
if(mat[i][col])
return -1;//无解
//接下来得枚举自由变元
int all=1<<(var-k);//var-k个自由变元,那么有2的指数次个状态
int t=0;
int res=0x3f3f3f3f;
for(j=k-1;j>=0;j--)
{
int temp=mat[j][var];
for(int l=j+1;l<var;l++)
temp^=mat[j][l]*x[l];
x[j]=temp;
if(x[j])
t++;
}
for(i=0;i<all;i++)
{
int cnt=t;
int index=i;
for(j=0;j<var-k;j++)
{
//x[free_x[j]]=(index&1);
if(index&1)//如果是1,则要反转,也就是要操作一次
cnt++;
index>>=1;
}
//同时还要判断确定的变量
if(cnt < res)
res = cnt;
}
return res;
}
char str[30];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
memset(mat,0,sizeof(mat));
memset(x,0,sizeof(mat));
memset(free_x,1,sizeof(free_x));
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
int t=i*n+j;
mat[t][t]=1;
if(i>0)
mat[(i-1)*n+j][t]=1;
if(i<n-1)
mat[(i+1)*n+j][t]=1;
if(j>0)
mat[i*n+j-1][t]=1;
if(j<n-1)
mat[i*n+j+1][t]=1;
}
for(int i=0;i<n;i++)
{
scanf("%s",str);
for(int j=0;j<n;j++)
{
if(str[j]=='y')
mat[i*n+j][n*n]=0;
else
mat[i*n+j][n*n]=1;
}
}
int res=Gauss(n*n,n*n);
if(res<0)
printf("inf\n");
else
printf("%d\n",res);
}
return 0;
}