题意:
现在有一个5行6列的灯阵,你需要给把他们全部关了。
当你翻转一盏灯的时候,上下左右也会被翻转。
每盏灯只能手动翻转一次。
要求输出一组能将所有灯关掉的解。
解法:
将每个位置弄出一个异或方程,5*6=30个位置就是30个异或方程,
解异或方程组用高斯消元。
构造异或方程原理:this
code:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int maxm=2e5+5;
int dx[]={0,0,0,1,-1};
int dy[]={0,1,-1,0,0};
int a[33][33];
int ans[5][6];
void gauss(){
for(int i=0;i<30;i++){
int k=i;
for(;k<30;k++)if(a[k][i])break;//找非0行
for(int j=0;j<=30;j++)swap(a[i][j],a[k][j]);
for(int j=0;j<30;j++){
if(i==j)continue;
if(a[j][i]){
for(int k=i;k<=30;k++){
a[j][k]^=a[i][k];
}
}
}
}
}
void get(){
for(int i=0;i<30;i++){
ans[i/6][i%6]=a[i][30];
}
}
signed main(){
int T;scanf("%d",&T);
int cas=1;
while(T--){
memset(a,0,sizeof a);
for(int i=0;i<30;i++){
scanf("%d",&a[i][30]);
}
for(int i=0;i<30;i++){
int x=i/6,y=i%6;
for(int k=0;k<5;k++){
int xx=x+dx[k];
int yy=y+dy[k];
if(xx<0||xx>=5||yy<0||yy>=6)continue;//上下左右中
a[i][xx*6+yy]=1;
}
}
gauss();
get();
printf("PUZZLE #%d\n",cas++);
for(int i=0;i<5;i++){
for(int j=0;j<6;j++){
printf("%d ",ans[i][j]);
}
puts("");
}
}
return 0;
}