[POJ1222]EXTENDED LIGHTS OUT(高斯消元)

题目描述

传送门
题意:给出一些01状态,按动一个按键与其相邻的4个和它本身的状态会取反,求使其全部变成0的按动方案。

题解

“开关问题”是异或方程组的经典问题,大概就是指定一些灯,每个灯的初始状态或开或关。每个灯有一个开关,每个开关还有一些相关的开关。如果按下一个开关,那么与之相关的开关都会被按下,相连的灯的开关状态都会改变,求让灯达到某个目标状态的方案。
可以发现灯的开关状态只和按下开关次数的奇偶性有关,那么可以构造异或方程组的模型。把每个开关按或没按设成未知量xi,如果按了就赋值为1,没按就赋值为0,那么可以发现某个灯状态改没改变取决于它自己的开关和所有与它相连的开关。按照相连状态建立矩阵,对于每个灯建立一个方程,把所有会影响到它的开关对应的系数赋值为1,不会影响到它的就赋值为0。常数项b对应着这个灯的目标状态,然后解异或方程组就可以了。

以上转自ATP的题解

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<bitset>
#include<cmath>
using namespace std;
#define N 35

int T,Case;
bitset<N>a[N];
int s[N][N],b[N],ans[N];

void clear()
{
    for (int i=1;i<=30;++i) a[i].reset();
    memset(b,0,sizeof(b));memset(ans,0,sizeof(ans));
}
void gauss()
{
    for (int i=1;i<=30;++i)
    {
        if (!a[i][i])
        {
            int num=i;
            for (int j=i+1;j<=30;++j)
                if (a[j][i]) {num=j;break;}
            swap(a[i],a[num]);swap(b[i],b[num]);
        }
        for (int j=i+1;j<=30;++j)
            if (a[j][i]) a[j]^=a[i],b[j]^=b[i];
    }
    for (int i=30;i>=1;--i)
    {
        ans[i]=b[i];
        for (int j=i-1;j>=1;--j)
            if (a[j][i]) b[j]^=ans[i];
    }
}
int main()
{
    scanf("%d",&T);
    while (T--)
    {
        clear();
        for (int i=1;i<=5;++i)
            for (int j=1;j<=6;++j) scanf("%d",&s[i][j]);
        for (int i=1;i<=5;++i)
            for (int j=1;j<=6;++j)
            {
                int now=(i-1)*6+j;
                a[now][now]=1;
                if (i!=1) a[now][now-6]=1;
                if (i!=5) a[now][now+6]=1;
                if (j!=1) a[now][now-1]=1;
                if (j!=6) a[now][now+1]=1;
                if (s[i][j]) b[now]=1;
            }
        gauss();
        printf("PUZZLE #%d\n",++Case);
        for (int i=1;i<=30;++i)
            printf("%d%c",ans[i]," \n"[i%6==0]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值