2000: 棋盘开关灯游戏 - 高斯消元|搜索

2000: 【高级算法】棋盘开关灯游戏
时间限制: 1 Sec 内存限制: 128 MB
提交: 37 解决: 23
[提交][状态][我的提交]
题目描述
一个棋盘状的开关阵列,排成5行6列。每个开关同时也是一个灯。按下一个开头后,受控制的灯就会改变状态:开->关,关->开。受控制的规则如下:
(1)角上的开关控制相邻的3个灯,如下图左上角的开关
(2)边上的开关控制相邻的4个灯,如下图底边的开关
(3)中间的开头控制相邻的5个灯,如下图第2行的开关

本题要解决的问题是:给出棋盘的初始状态,请确定按下哪些开关,使得棋盘上的所有灯就熄灭。

输入
第1行:1个整数n,表示测试数据的组数
接下来n组数据,每组5行,每行6个空格分开的整数,0表示关,1表示开。
输出
每组数据,输出一个5行6列的01阵列,0表示不按某个开关,1表示要按某个开关

每组数据之间用一个空行分隔

样例输入
2
0 1 1 0 1 0
1 0 0 1 1 1
0 0 1 0 0 1
1 0 0 1 0 1
0 1 1 1 0 0
0 0 1 0 1 0
1 0 1 0 1 1
0 0 1 0 1 1
1 0 1 1 0 0
0 1 0 1 0 0
样例输出
1 0 1 0 0 1
1 1 0 1 0 1
0 0 1 0 1 1
1 0 0 1 0 0
0 1 0 0 0 0

1 0 0 1 1 1
1 1 0 0 0 0
0 0 0 1 0 0
1 1 0 1 0 1
1 0 1 1 0 1

高斯消元异或方程:(0^1=1,1^1=0 => 关^改变状态=开 开^改变状态=关 )
未知数是对于每个灯的开关状态
方程根据每个灯受到的其他灯的影响列出

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 30
const int n=5,m=6;
int dir[10][3]={{0,0},{0,1},{0,-1},{1,0},{-1,0}};
int a[MAXN+10][MAXN+10],id[MAXN+10][MAXN+10];

void Debug()
{
    for(int i=1;i<=n*m;i++){
            for(int j=1;j<=m*n+1;j++)
                printf("%d ",a[i][j]);
            printf("\n");
            }
}
void read()
{
    int x,y;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&a[id[i][j]][n*m+1]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=0;k<5;k++){
                x=i+dir[k][0],y=j+dir[k][1];
                if(x>=1&&x<=n&&y>=1&&y<=m)
                    a[id[x][y]][id[i][j]]=1;
            }
}
void GJ_elimination(int equ,int var,int &row,int &col)
{
    int mx;
    for(row=col=1;row<=equ&&col<=var;row++,col++){
        mx=row;
        for(int i=row+1;i<=equ;i++){
            if(a[i][col]>a[mx][col])
                mx=i;
            if(a[mx][col]==1)
                break;
        }
        if(mx!=row)
            swap(a[row],a[mx]);
        if(a[row][col]==0){ //本题有唯一解,这句if可以不要
            row--;
            continue;
        }
        for(int i=1;i<=equ;i++){
            if(i==row||a[i][col]==0)
                continue;
            for(int j=var+1;j>=1;j--)
                a[i][j]^=a[row][j];
        }
    }
}
void Gauss_Jordan(int equ,int var)
{
    int row,col;
    GJ_elimination(equ,var,row,col);
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            id[i][j]=(i-1)*m+j;//,printf("%d\n",id[i][j]);
    while(T--){
        memset(a,0,sizeof a);
        read();
        Gauss_Jordan(n*m,n*m);
        for(int i=1;i<=n*m;i++){
            printf("%d",a[i][n*m+1]);
            if(i%m==0) printf("\n");
            else printf(" ");
        }
        puts("");
    }
}

搜索代码写了再更新。

posted @ 2016-01-31 10:16  KatarinaYuan  阅读(499)  评论(0编辑  收藏  举报