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;
}

 

posted @ 2017-08-16 16:43  猪突猛进!!!  阅读(125)  评论(0编辑  收藏  举报