您的位置:首页 > 其它

POJ1222 EXTENDED LIGHTS OUT 高斯消元入门

2017-08-18 21:42 417 查看
题目链接:POJ1222

参考来源:大佬的题解

关于这个知识点我翻了许多博客,最后找到这一篇讲的十分清楚,所以转在这里。部分代码加了自己的注释,方便大家更容易看明白。

题意:给出一个5*6的图,每个灯泡有一个初始状态,1表示亮,0表示灭。每对一个灯泡操作时,会影响周围的灯泡改变亮灭,问如何操作可以使得所有灯泡都关掉。

思路:因为每盏灯,如果操作两次就相当于没有操作,所以相当于(操作次数)%2,即异或操作。

考虑一个2*3的图,最后需要的状态是 :

,如果初始状态为:

。对这两个矩阵的每个数字做异或操作可以得到线性方程组每个方程的答案。

总共6盏灯,0-5。那么可以列出6个方程。

对于第0盏灯,会影响到它的是第0, 1, 3盏灯,因此可以列出方程1*x0 + 1*x1 + 0*x2 + 1*x3 + 0*x4 + 0*x5= 0。

对于第1盏灯,会影响到它的是第0, 1, 2,4盏灯,因此可以列出方程1*x0 + 1*x1 + 1*x2 + 0*x3 + 1*x4 + 0*x5 = 1。

对于第2盏灯,会影响到它的是第1, 2, 5盏灯,因此可以列出方程0*x0 + 1*x1 + 1*x2 + 0*x3 + 0*x4 + 1*x5 = 0。

.....

所以最后可以列出增广矩阵:


然后用高斯消元求这个矩阵的解就可以了。

AC代码:

/*
2017年8月18日21:35:13
POJ1222
高斯消元解异或方程组模板
AC
*/
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;

const int maxn=8;
int a[maxn*maxn][maxn*maxn];
int x[maxn*maxn];
int mp[maxn][maxn];

void init(){
memset(a,0,sizeof(a));
for(int i=0;i<5;i++){
for(int j=0;j<6;j++){
int pos=i*6+j;
a[pos][pos]=1;//当前位置
if(j>0) a[pos][i*6+j-1]=1;//当前位置的左边
if(j<5) a[pos][i*6+j+1]=1;//当前位置的右边
if(i>0) a[pos][(i-1)*6+j]=1;//当前位置的上边
if(i<4) a[pos][(i+1)*6+j]=1;//当前位置的下边
}
}
}

void Gauss(int n,int m){
memset(x,0,sizeof(x));
int r,c;
for(r=0,c=0;r<n&&c<m;r++,c++){
int max_r=r;
for(int i=r+1;i<n;i++){
if(fabs(a[i][c])>fabs(a[max_r][c])) max_r=i;
}
if(a[max_r][c]==0){
r--;
continue;//处理当前行的下一个位置,或者说下一列
}
if(max_r!=r){
//交换这两行从第C列开始的元素,包括第m行
for(int i=c;i<m+1;i++) swap(a[max_r][i],a[r][i]);
}
for(int i=r+1;i<n;i++){
if(a[i][c]==0) continue;//如果该行第一个元素的值为0,跳过
for(int j=c;j<m+1;j++) a[i][j]=a[i][j]^a[r][j];
}
}
for(int i=m-1;i>=0;i--){
x[i]=a[i][m];
for(int j=i+1;j<m;j++){
x[i]=x[i]^(a[i][j]&&x[j]);
}
}
}

int main(){
int t,kase=0;
scanf("%d",&t);
while(t--){
init();
for(int i=0;i<5;i++){
for(int j=0;j<6;j++){
scanf("%d",&a[i*6+j][30]);
}
}

Gauss(30,30);
printf("PUZZLE #%d\n",++kase);
for(int i=0;i<5;i++){
for(int j=0;j<6;j++){
if(!j) printf("%d",x[i*6+j]);
else printf(" %d",x[i*6+j]);
}printf("\n");
}

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: