hihoCoder1196 (高斯消元)

#1196 : 高斯消元·二

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

在上一回中,小Hi和小Ho趁着便利店打折,买了一大堆零食。当他们结账后,看到便利店门口还有其他的活动。

店主:买了东西还可以参加游戏活动哦,如果能够完成游戏还有额外的奖品。

小Hi和小Ho赶紧凑了过去。

店主放了一块游戏板在店门口,有5行6列格子。左上角为坐标(1,1)。一部分格子是亮着的,另一部分是暗着的。

 当按下某一个格子时,它和上下左右4个格子的状态就会改变。原来亮着的格子变成暗的,原来暗的格子会变亮。比如下图中按下标记有红叉的格子后,绿色虚线区域内的格子状态都会改变:

店主给出初始的状态,参加游戏的人员需要通过按下某些格子,让游戏板上所有的灯都亮起来就可以赢得奖品。

小Ho:这不就是开关灯问题么,看我来解决它!

 

输入

第1..5行:1个长度为6的字符串,表示该行的格子状态,1表示该格子是亮着的,0表示该格子是暗的。

保证一定存在解,且一定存在暗着的格子。

输出

需要按下的格子数量k,表示按下这k个位置后就可以将整个游戏板所有的格子都点亮。

接下来k行,每行一个坐标(x,y),表示需要按下格子(x,y)。x坐标较小的先输出,若x相同,则先输出y坐标较小的。

样例输入
001111
011111
111111
111110 
111100
样例输出
2
1 1
5 6

分析:上面的提示说的很清楚,建一个30个未知数的方程组,

然后用高斯消元解方程,因为方程保证一定有解所以不用判断无解的情况。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[40][40];
int num[7][7];
int d[5][2]={0,1,0,-1,1,0,-1,0,0,0};

void Guass()
{
    int N=30,M=31;//N行 
    for(int i=1;i<=N;i++)//计算上三角 
    {
        if(a[i][i]==0)
        {
            int k=N;
            for(;k>i;k--)
            if(a[k][i]!=0) break;
            swap(a[k],a[i]);//交换两行 
        }
        
        for(int k=i+1;k<=N;k++)
        {
            if(a[k][i]==0) continue;//这里要判断一下
            for(int j=i+1;j<=M;j++)
            a[k][j]=a[k][j]^a[i][j];
            a[k][i]=0;
        }
    }
    
    //从下往上消去
    int ans=0;
    for(int i=N;i;i--) 
    {
        for(int k=i-1;k;k--)
        {
            if(a[k][i]==0) continue;//这里要判断一下
            a[k][M]=a[k][M]^a[i][M];
            a[k][i]=0;
        }
    }
}

int main()
{
    int cnt=1,x;
    for(int i=1;i<=5;i++)
    for(int j=1;j<=6;j++)
    {
        scanf("%1d",&x);
        a[cnt][31]=1^x;//当前状态^最终状态 
        num[i][j]=cnt++;
    }
    
    for(int i=1;i<=5;i++)
    {
        for(int j=1;j<=6;j++)
        {
            int t=num[i][j];//第t行
            for(int k=0;k<5;k++) 
            a[t][num[i+d[k][0]][j+d[k][1]]]=1;
        }
    }
    Guass();
    int ans=0;
    for(int i=1;i<=30;i++) if(a[i][31]) ans++;
    printf("%d\n",ans);
    for(int i=1;i<=30;i++)
    {
        if(a[i][31]==0) continue;
        printf("%d %d\n",(i-1)/6+1,(i-1)%6+1);
    }
    
    return 0;
}
View Code

 

posted @ 2018-04-06 21:10  ACRykl  阅读(155)  评论(0编辑  收藏  举报