题意
给你$5 \times 6$ 的一些灯,每个灯有亮和灭两种状态。当按下某个灯的开关时,它和它相邻的灯都会改变状态(亮变灭,灭变亮)。
现在给你这些灯的初始状态,问你将其都按灭的话,哪些开关要按下。
思路
思路同HDU 3359 Kind of a Blur.
不同的是这里最终答案只有0
和1
两种,异或高斯消元即可。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <iostream>
#include <map>
#include <set>
//#define test
using namespace std;
const int Nmax=1e3+7;
typedef long long ll;
typedef int ld;
int n,m,t;
int dx[]={0,0,0,1,-1};
int dy[]={0,1,-1,0,0};
ld a[Nmax][Nmax];
ld ans[Nmax][Nmax];
int size;
void init()
{
size=0;
memset(ans,0,sizeof(ans));
}
void gaussJordan(int n,ld a[][Nmax])
{
for(int i=1;i<=n;i++)
{
int idx=i;
for(int j=i+1;j<=n;j++)
if(abs(a[idx][i])<abs(a[j][i]))
idx=j;
if(idx!=i)
{
for(int j=i;j<=n+1;j++)
swap(a[idx][j],a[i][j]);
}
if(!a[i][i])
continue;
for(int j=1;j<=n;j++)
{
if(j!=i && a[j][i])
{
for(int k=i;k<=n+1;k++)
a[j][k]^=a[i][k];
}
}
}
//for(int i=1;i<=n;i++)
//{
//a[i][n+1]/=a[i][i];
//a[i][i]=1;
//}
}
int id(int x,int y)
{
return (x-1)*m+y;
}
void show()
{
for(int i=1;i<=n*m;i++)
for(int j=1;j<=n*m+1;j++)
printf("%d%c",ans[i][j],j==n*m+1?'\n':' ');
}
int dis(int x,int y,int xx,int yy)
{
return abs(xx-x)+abs(yy-y);
}
int main()
{
#ifdef test
#endif
//freopen("l.in","r",stdin);
n=5,m=6;
int t;
scanf("%d",&t);
for(int cases=1;cases<=t;cases++)
{
printf("PUZZLE #%d\n",cases);
init();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
++size;
ans[size][id(i,j)]=1;
for(int k=1;k<=4;k++)
{
int nowx=i+dx[k],nowy=j+dy[k];
if(nowx<1 || nowx>n || nowy<1 || nowy>m)
continue;
ans[size][id(nowx,nowy)]=1;
}
ans[size][n*m+1]=a[i][j];
}
}
#ifdef test
show();
#endif
gaussJordan(n*m,ans);
#ifdef test
printf("after:\n");
show();
#endif
for(int i=1;i<=n*m;i++)
printf("%d%c",ans[i][n*m+1],i%m==0?'\n':' ');
}
return 0;
}