POJ 1222 EXTENDED LIGHTS OUT [高斯消元XOR]

题意:

$5*6$网格里有一些灯告诉你一开始开关状态,按一盏灯会改变它及其上下左右的状态,问最后全熄灭需要按那些灯,保证有解


经典问题

一盏灯最多会被按一次,并且有很明显的异或性质

一个灯作为一个方程一个变量

两盏灯相互影响系数设为1

常数项代表最后需不需要这盏灯改变状态

解这个异或方程组就行了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bitset>
using namespace std;
const int N=35;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int n=30,_;
bitset<N> a[N];
void ini(){
    for(int i=1;i<=n;i++) a[i].reset();
}
char s[N];
void Gauss(){
    int now=1;
    for(int i=1;i<=n;i++){
        int j=now;
        while(j<=n&&!a[j][i]) j++;
        if(now!=j) swap(a[now],a[j]);
        for(int k=1;k<=n;k++) 
            if(k!=now&&a[k][i]) a[k]^=a[now];
        now++;
    }
}
int main(){
    freopen("in","r",stdin);
    int T=read(),cas=0;
    while(T--){
        for(int i=1;i<=5;i++)
            for(int j=1;j<=6;j++){
                int id=(i-1)*6+j;
                a[id][id]=1;
                if(i!=1) a[id][id-6]=1;
                if(i!=5) a[id][id+6]=1;
                if(j!=1) a[id][id-1]=1;
                if(j!=6) a[id][id+1]=1;
                a[id][n+1]=read();
            }
        Gauss();
        printf("PUZZLE #%d
",++cas);
        for(int i=1;i<=5;i++)
            for(int j=1;j<=6;j++) 
                _=(i-1)*6+j,printf("%d%c",a[_][n+1]==1?1:0,j==6?'
':' ');
    }
}
原文地址:https://www.cnblogs.com/candy99/p/6409880.html