您的位置:首页 > 其它

POJ 1222 开关问题高斯消元法

2016-08-24 17:01 337 查看
一个01矩阵,表示灯的亮灭状态,每次操作可以改变一个十字形状内的五个灯的状态。问能否将所有灯熄灭。

最后输出开关的状态。

思路:

开灯关灯问题,5*6的灯阵,将每一个位置上开关状态看做一个变元,30个变元,而对于30个位置的灯的状态当成开关状态的解,列出30个异或方程,高斯消元解方程即可(增广矩阵)。

对于每个状态,影响他的条件与五个位置的开关状态有关,让这五个状态的开关系数为1 ,其他的系数为0,表示无影响。

最后输出30个开关的状态即可。

开关问题,一个开关最多只会被按1次。

各个按钮被按下的顺序对最终的结果没有影响;

详情看代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define LL long long
#define bug puts("************")
using namespace std;
const int N=110;
int a

;
int dx[]={-1,1,0,0,0};
int dy[]={0,0,1,-1,0};
int xx
;
void guess(int equ,int var){
int k=0,cul,r;
for(k=0,cul=0;k<equ&&cul<var;k++,cul++){
r=k;
for(int i=k;i<equ;i++){
if(a[i][cul]){
r=i;break;
}
}
if(!a[r][cul]){
k--;continue;
}
if(r!=k){
for(int j=0;j<var+1;j++)swap(a[k][j],a[r][j]);
}
for(int i=k+1;i<equ;i++){
if(a[i][cul]){
for(int j=0;j<var+1;j++)
a[i][j]=a[i][j]^a[k][j];
}
}
}
///唯一解回代。
for(int i=var-1;i>=0;i--){
xx[i]=a[i][var];
for(int j=i+1;j<var;j++)
xx[i]^=(a[i][j]&&xx[j]);
}
for(int i=0;i<equ;i++){
printf("%d%s",xx[i],(i+1)%6!=0?" ":"\n");
}
}
int main(){
int t;
scanf("%d",&t);
for(int ca=1;ca<=t;ca++){
memset(a,0,sizeof(a));
for(int i=0;i<30;i++){
scanf("%d",&a[i][30]); ///方程的解。
}
printf("PUZZLE #%d\n",ca);
for(int i=0;i<5;i++){
for(int j=0;j<6;j++){
for(int k=0;k<5;k++){
int fx=dx[k]+i;
int fy=dy[k]+j;
if(fx<0||fy<0||fx>=5||fy>=6)continue;
a[i*6+j][fx*6+fy]=1; ///通过系数来决定该位置是否对解有影响。
}
}
}
// for(int i=0;i<30;i++){
// for(int j=0;j<30;j++)
// printf("%d ",a[i][j]);
// cout<<endl;
// }
guess(30,30);
}
return 0;
}

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