poj 1224
题意:有一个5 * 6的矩阵,每个位置表示灯,1表示灯亮,0表示灯灭。
然后如果选定位置i,j点击,则位置i,j和其上下左右的灯的状态都会反转。
现在要你求出一个5 * 6的矩阵,1表示这个灯被点击过,0表示没有。
要求这个矩阵能够使得原矩阵的灯全灭。
题解:构造一个30 X 31增广矩阵(一个有30个目标结果,所以方程组的个数为30,然后可用的变量个数为30 ,增广一下就是30 X 31了)然后异或高斯就可以了。
ac代码:
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; int mp[6][7]; int x[33]; int a[33][33]; void init() { memset(x,0,sizeof(x)); memset(a,0,sizeof(a)); } int check(int x,int y) { if(x<=0 || x>=6 || y<=0 || y>=7) return -1; return 1; } void Debug(int n,int m) { for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) cout<<a[i][j]<<' '; cout<<endl; } } void gauss() { int max_r; int col,k; int i,j; for(int z=1;z<=5;z++) { for(int zz=1;zz<=6;zz++) { i=(z-1)*6+zz;// row j=(z-1)*6+zz; a[i][31]=mp[z][zz]; a[i][j]=1; for(int low=0;low<4;low++)// 里面的一一对应 求集中注意力写/。。。 { int xx=z+dir[low][0]; int yy=zz+dir[low][1]; if(check(xx,yy)==1) //attention !! 这个条件都写错了,, 里面不成立写的是-1 所以外面要注意一点。。 { j=(xx-1)*6+yy; // cout<<low<<' '<<xx<<' '<<yy<<endl; a[i][j]=1; } } } } // Debug(30,31); col=k=1; while( k<=30 && col<=30) // 阶梯化 { max_r=k; for(int u=k;u<=30;u++) if(a[u][col]) { max_r=u; // find max break; } if(a[max_r][col]!=0) { if(max_r!=k) // not the frist ont swap it { for(int u=0;u<=31;u++) swap(a[max_r][u],a[k][u]); } for(int u=k+1;u<=30;u++) { if(a[u][col]) { for(int z=0;z<=31;z++) a[u][z]^=a[k][z]; } } k++; } col++; } //Debug(30,31); int temp=0; for(int z=30;z>=1;z--) { x[z]=a[z][31]; for(int zz=z+1;zz<=30;zz++) if(a[z][zz]) { x[z]^=x[zz]; } } } int main() { int t; scanf("%d",&t); int Case=0; while(t--) { for(int i=1;i<=5;i++) { for(int j=1;j<=6;j++) scanf("%d",&mp[i][j]); } init();//a x gauss(); // 还有一个点 就是方程的构造问题 printf("PUZZLE #%d\n",++Case); for(int i=1;i<=30;i++) { if(i%6!=0) printf("%d ",x[i]); else printf("%d\n",x[i]); } } return 0; }