您的位置:首页 > 其它

poj1222高斯消元解XOR方程

2016-03-27 21:22 309 查看
http://poj.org/problem?id=1222

题意:给定一个5×6的的矩阵,每次可以选择一个,使得它和四周的值翻转(开关变向),问怎样操作使得全为0.

(PS:我交C++给我CE了,它不让我直接swap二维数组的第一维;G++给了我开了个优化)。

利用高斯消元。

我们可以得到30个方程。

套用之前的思路,把f[][]看成是i,j是否相连,然后就会有一系列形如: x1*f[1][1] ^  x2*f[2][1]  ^ x3*f[3][1]``````=b[1]      b[1]表示1的最终状态,其它的以此类推。

如果之前1的位置是1,那么我们得到的方程的值b[1]一定也是1,表示这盏灯最终被操作过(变换过),这样才能保证最后是0; 如果之前1的位置是0,我们就要保证这盏灯相当于没有操作过。

然后搞出一个矩阵求解,套一下版就好了(这里应该是不存在无解的情况的)。

参考建立系数矩阵f的系列操作:

for(int i=1;i<=5;i++)
{
for(int j=1;j<=6;j++)
{
int id=get(i,j);
scanf("%d",&f[id][31]);//每一组方程的解
}
}
for(int i=1;i<=5;i++)
{
for(int j=1;j<=6;j++)
{
int id=get(i,j);
f[id][id]=1;//自我联通
for(int k=0;k<4;k++)
{
int x=i+dx[k];
int y=j+dy[k];
int idx=get(x,y);
if(x>=1&&x<=5&&y>=1&&y<=6)//上下左右联通
{
f[id][idx]=1;
}
}
}
}

全代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
const int maxn=35;
int f[maxn][maxn];
int get(int i,int j)
{
return (i-1)*6+j;
}
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int is[maxn];
int ans[maxn];
int tot;
void solve()
{
int k=1;
tot=0;
memset(is,0,sizeof(is));
int j;
for(int i=1;;i++)
{
if(i==31)
{
for(j=k;j<=30;j++)
{
if(f[j][31])
{
printf("-1\n");
return ;
}
}
}
for(j=k;j<=30;j++)if(f[j][i])break;
if(j==31)
{
is[i]=++tot;
continue;
}
swap(f[j],f[k]);
for(j=k+1;j<=30;j++)
{
if(f[j][i])
{
for(int l=i;l<=31;l++)f[j][l]^=f[k][l];
}
}
k++;
if(k>30)break;
}
}
void get_ans()
{
memset(ans,0,sizeof(ans));
for(int i=30;i;i--)
{
ans[i]=f[i][31];
for(int j=i+1;j<=30;j++)if(f[i][j])ans[i]^=ans[j];
}

for(int i=1;i<=5;i++)
{
for(int j=1;j<=6;j++)
{
printf("%d ",ans[get(i,j)]);
}
printf("\n");
}
}
int main()
{
int T;
scanf("%d",&T);
int cas=0;
while(T--)
{
printf("PUZZLE #%d\n",++cas);
memset(f,0,sizeof(f));
for(int i=1;i<=5;i++)
{
for(int j=1;j<=6;j++)
{
int id=get(i,j);
scanf("%d",&f[id][31]);
}
}
for(int i=1;i<=5;i++)
{
for(int j=1;j<=6;j++)
{
int id=get(i,j);
f[id][id]=1;
for(int k=0;k<4;k++)
{
int x=i+dx[k];
int y=j+dy[k];
int idx=get(x,y);
if(x>=1&&x<=5&&y>=1&&y<=6)
{
f[id][idx]=1;
}
}
}
}
solve();
get_ans();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  bzoj 高斯消元