zoukankan      html  css  js  c++  java
  • 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
    ",ans);
        for(int i=1;i<=30;i++)
        {
            if(a[i][31]==0) continue;
            printf("%d %d
    ",(i-1)/6+1,(i-1)%6+1);
        }
        
        return 0;
    }
    View Code
  • 相关阅读:
    WinForm 防止因为各种因素的操作导致主窗体冻结、卡死的解决方法
    winform常用知识点
    数字金额转为大写金额(C#)
    中关村网站产品参数页的参数纠错的制作
    牛腩自制TXT文本分割工具
    delphi连接SQL2005做的数据库管理系统的一些部署问题
    我的WIN7 RC+汉化安装步骤
    求一整数的所有拆分方式
    全角字符与半角字符的相互转换(C#)
    一道.NET题
  • 原文地址:https://www.cnblogs.com/ACRykl/p/8728909.html
Copyright © 2011-2022 走看看