模板:http://www.cnblogs.com/kuangbin/archive/2012/09/01/2667044.html
poj 1222 EXTENDED LIGHTS OUT
题意:有5行6列的灯。每次按一下某一个,那么范围内上下左右包括自己的状态都会改变,如果是亮的,就变灭,反之如果是灭的将被点亮。用1代表亮,用0表示灭。每个灯只能按一次,因为按两次又变回原状态。给定灯的初始状态,问怎么按使得灯全灭。
思路:http://blog.csdn.net/u013508213/article/details/47263183
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[40][40];
int x[40];//解集
int Gauss(int equ,int var)
{
int maxrow;
int row=0,col=0;
for(;row<equ&&col<var;row++,col++)
{
maxrow=row;
for(int k=row+1;k<equ;k++)
if(abs(a[k][col])>abs(a[maxrow][col]))maxrow=k;
if(maxrow!=row)
{
for(int j=row;j<=var;j++)//
swap(a[maxrow][j],a[row][j]);
}
if(a[row][col]==0)
{
row--;
continue;
}
for(int i=row+1;i<equ;i++)
{
if(a[i][col]!=0)
{
for(int j=0;j<=var;j++)
a[i][j]=a[i][j]^a[row][j];
}
}
}
for(int i=var-1;i>=0;i--)
{
x[i]=a[i][var];
for(int j=i+1;j<var;j++)
x[i]=x[i]^(a[i][j]&&x[j]);
}
return 0;
}
int main()
{
int t,cas=0;
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
scanf("%d",&t);
while(t--)
{
memset(a,0,sizeof(a));
memset(x,0,sizeof(x));
for(int i=0;i<5;i++)
{
for(int j=0;j<6;j++)
{
int t=i*6+j;
a[t][t]=1;
if(i>0)a[(i-1)*6+j][t]=1;
if(i<4)a[(i+1)*6+j][t]=1;
if(j>0)a[i*6+j-1][t]=1;
if(j<5)a[i*6+j+1][t]=1;
scanf("%d",&a[t][30]);
}
}
Gauss(30,30);
printf("PUZZLE #%d\n",++cas);
for(int i=0;i<30;i++)
{
printf("%d",x[i]);
if((i+1)%6==0)printf("\n");
else printf(" ");
}
}
}
poj 1681 Painter's Problem
http://poj.org/problem?id=1681
和poj1222类似,将开关换成颜色。可能存在无解,多解,枚举自由变元。算出最小值。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 16;
int a[maxn*maxn][maxn*maxn];
int x[maxn*maxn];//解集
int free_x[maxn*maxn];
int num;
int Gauss(int equ,int var)
{
int maxrow;
int row=0,col=0;
num=0;
for(;row<equ&&col<var;row++,col++)
{
maxrow=row;
for(int k=row+1;k<equ;k++)
if(abs(a[k][col])>abs(a[maxrow][col]))maxrow=k;
if(maxrow!=row)
{
for(int j=row;j<=var;j++)//
swap(a[maxrow][j],a[row][j]);
}
if(a[row][col]==0)
{
row--;
free_x[num++]=col;//说明“对角线”上系数为0
continue;
}
for(int i=row+1;i<equ;i++)
{
if(a[i][col]!=0)
{
for(int j=0;j<=var;j++)
a[i][j]=a[i][j]^a[row][j];
}
}
}
for(int i=row;i<equ;i++)//无解 0~row-1 非零行 row~equ-1 零行 秩为row 自由变元个数 var - row
if(a[i][col]!=0)return -1;
int s=1<<(var-row);
int min = 1<<30;
for(int i=0;i<s;i++)//二进制枚举所有自由变元取值
{
int cnt=0;
int index=i;
for(int j=0;j<var-row;j++)
{
x[free_x[j]]=(index&i);
if(x[free_x[j]])cnt++;
index>>=1;
}
for(int k=row-1;k>=0;k--)
{
int temp=a[k][var];
for(int j=k+1;j<var;j++)
temp^=(x[j]*a[k][j]);
x[k]=temp;
if(x[k])cnt++;
}
if(cnt<min)
{
min=cnt;
}
}
return min;
}
void init(int n)
{
memset(a,0,sizeof(a));
memset(x,0,sizeof(x));
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
int t=i*n+j;
a[t][t]=1;
if(i>0)a[(i-1)*n+j][t]=1;
if(i<n-1)a[(i+1)*n+j][t]=1;
if(j>0)a[i*n+j-1][t]=1;
if(j<n-1)a[i*n+j+1][t]=1;
}
}
}
int main()
{
int t;
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
scanf("%d",&t);
while(t--)
{
int n;
char s[100];
scanf("%d",&n);
init(n);
for(int i=0;i<n;i++)
{
scanf("%s",s);
for(int j=0;j<n;j++)
{
if(s[j]=='y')a[i*n+j][n*n]=0;
else if(s[j]=='w')a[i*n+j][n*n]=1;
}
}
int ans=Gauss(n*n,n*n);
if(ans==-1)
printf("inf\n");
else
printf("%d\n",ans);
}
}