POJ 1222 EXTENDED LIGHTS OUT(高斯消元解XOR方程组)

http://poj.org/problem?id=1222

题意:
现在有5*6的开关,1表示亮,0表示灭,按下一个开关后,它上下左右的灯泡会改变亮灭状态,要怎么按使得灯泡全部处于灭状态,输出方案,1表示按,0表示不按。

思路:
每个开关最多只按一次,因为按了2次之后,就会抵消了。

可以从结果出发,也就是全灭状态怎么按能变成初始状态。

用3*3来举个例子,$X\left ( i,j \right )$表示这些开关是按还是不按,那么对于第一个开关,对它有影响的就只有2、4这两个开关,所以它的异或方程组就是:

$X\left ( 1,1 \right )*A\left ( 1,1 \right )  XOR  X\left ( 2,2 \right )*A\left ( 2,2 \right )...XOR  X\left ( 9,9 \right )*A\left ( 9,9 \right ) = $初始状态

这样一来就有30个异或方程组,高斯消元解一下即可。

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn = + ; int ans[maxn];
int c[maxn][maxn]; void Gauss()
{
int i=,j=,k,r;
for(k=;k<;k++) //现在处理第k行
{
i=k;
while(c[i][k]== && i<) i++; //找到一行第k列元素不为0
if(i!=k) for(j=;j<=;j++) //交换两行
swap(c[k][j],c[i][j]); //消元与回代合并了
for(i=;i<;i++) if(k!=i && c[i][k])
for(j=k;j<=;j++) c[i][j]=c[k][j]^c[i][j];
}
for(int i=;i<;i++)
ans[i]=c[i][];
} int main()
{
//freopen("in.txt","r",stdin);
int T;
int kase=;
scanf("%d",&T);
while(T--)
{
memset(c,,sizeof(c));
for(int i=;i<;i++) scanf("%d",&c[i][]); for (int i=;i<;i++)
{
c[i][i]=;
if (i%!=) c[i-][i]=;
if (i%!=) c[i+][i]=;
if (i>) c[i-][i]=;
if (i<) c[i+][i]=;
} Gauss();
printf ("PUZZLE #%d\n",++kase);
for (int i=;i<;i++)
printf (i%==?"%d\n":"%d ",ans[i]);
}
return ;
}
上一篇:OnPaint()函数的作用原理


下一篇:Quartz源码——JobStore保存JonDetail和Trigger源码分析(一)