【POJ】1222 EXTENDED LIGHTS OUT

本文介绍了一种使用高斯消元法解决异或方程组的方法,并通过一个具体的例子详细展示了如何建立异或方程组、进行高斯消元的过程以及最终求解结果。

【算法】高斯消元

【题解】

高斯消元经典题型:异或方程组

poj 1222 高斯消元详解

异或相当于相加后mod2

异或方程组就是把加减消元全部改为异或。

异或性质:00 11为假,01 10为真。与1异或取反,与0异或不变。

建图:对于图上每个点x列一条异或方程,未知数为n个灯按不按,系数为灯i按了点x变不变,该行结果n+1为初始状态。(所以a[x][y]其实表示x和y是否存在异或关系)

建图原理见上面链接。

寻找:因题目保证有解,而系数只有0或1,所以不用找最大,找到一个非0系数即可。

消元:只针对对应变量系数为1的,全部异或即可。

回代:因为每行的主元素i系数必为1,所以该行结果一定与该行主元素相同(1*x=x)

因此只要把i+1~n的系数为1的结果与该行结果异或即可。

注意打印编号的时候要从0累加,而不是用累减的数据组数……

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int n=30;
int tt,a[n+10][n+10];
void gauss()//保证有解 
{
    int r;
    for(int i=1;i<=n;i++)
     {
         for(int j=i;j<=n;j++)if(a[j][i]){r=j;break;}
         if(r!=i)for(int j=1;j<=n+1;j++)swap(a[i][j],a[r][j]);
         for(int j=i+1;j<=n;j++)if(a[j][i])
          for(int k=i;k<=n+1;k++)
           a[j][k]^=a[i][k];
     }
    for(int i=n;i>=1;i--)
     for(int j=i+1;j<=n;j++)
      if(a[i][j])a[i][n+1]^=a[j][n+1];
}
int main()
{
    scanf("%d",&tt);
    int t=0;
    while(tt--)
     {
         t++;
         memset(a,0,sizeof(a));
         for(int i=1;i<=n;i++)
         {
             scanf("%d",&a[i][n+1]);
             a[i][i]=1;
             if(i%6!=1)a[i][i-1]=1;
             if(i%6!=0)a[i][i+1]=1;
             if(i>6)a[i][i-6]=1;
             if(i<25)a[i][i+6]=1;
         }
        gauss();
        printf("PUZZLE #%d\n",t);
        for(int i=1;i<=n;i++)
         {
             if(!(i%6))printf("%d\n",a[i][n+1]);
             else printf("%d ",a[i][n+1]);
         }
     }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/onioncyc/p/6613149.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值