POJ 1222 EXTENDED LIGHTS OUT(异或方程组高斯消元)

题目在这里>_<

题意

给你$5 \times 6$ 的一些灯,每个灯有亮和灭两种状态。当按下某个灯的开关时,它和它相邻的灯都会改变状态(亮变灭,灭变亮)。
现在给你这些灯的初始状态,问你将其都按灭的话,哪些开关要按下。

思路

思路同HDU 3359 Kind of a Blur.
不同的是这里最终答案只有01两种,异或高斯消元即可。

代码

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