zoukankan      html  css  js  c++  java
  • POJ 1222 EXTENDED LIGHTS OUT (高斯消元)

    题目链接

    题意:5*6矩阵中有30个灯,操作一个灯,周围的上下左右四个灯会发生相应变化 即由灭变亮,由亮变灭,如何操作使灯全灭?

    题解:这个问题是很经典的高斯消元问题。同一个按钮最多只能被按一次,因为按两次跟没有按是一样的效果。那么 对于每一个灯,用1表示按,0表示没有按,那么每个灯的状态的取值只能是01。列出30个方程,30个变元,高斯消元解出即可。打表观察我们可以发现5*6的矩阵是一定有解的,主对角线元素都是1所以一定有唯一解

    打表代码:

    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    char s[300][300];
    int g[300][300],ans[300];//注意这里定义的大小是n^2 不是n
    int dir[5][2]= {{0,0},{0,1},{0,-1},{1,0},{-1,0}};
    int n,m1,m2;
    int gauss()
    {
        int row,col;
        for(row=0,col=0; row<n&&col<n; col++) //注意是小于n
        {
            int id=row;
            for(int i=row+1; i<n; i++)
                if(g[i][col]) id=i;
            if(g[id][col])
            {
                for(int k=col; k<=n; k++)
                    swap(g[id][k],g[row][k]);//注意这里是k
                for(int j=row+1; j<n; j++)
                    if(g[j][col])
                        for(int k=col; k<=n; k++) //注意这里每段代码的特点 一点都不能写错
                            g[j][k]^=g[row][k];
                row++;//一定注意这句话放到if里
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            printf("%d ",g[i][j]);
            printf("   *******
    ");
        }
    //    for(int i=row; i<n; i++)
    //        if(g[i][n]) return -1;
    //    int ans=0;
    //    for(int i=n-1; i>=0; i--)
    //    {
    //        for(int j=n-1; j>i; j--)
    //            g[i][n]^=g[i][j]&&g[j][n];
    //        ans+=g[i][n];
    //    }
    //    return ans;
        return -1;
    }
    int main()
    {
    
        m1=5;m2=6;
        n=m1*m2;
        //1
        memset(g,0,sizeof(g));
        for(int i=0; i<m1; i++)
            for(int j=0; j<m2; j++)
                for(int k=0; k<5; k++)
                {
                    int a=i+dir[k][0];
                    int b=j+dir[k][1];
                    if(a>=0&&b>=0&&a<m1&&b<m2)
                        g[a*m2+b][i*m2+j]=1; //注意这里是 *m2, 模拟几个数就能理解了
                }
        int ans1,ans2;
        ans1=gauss();
        return 0;
    }

    AC代码:

    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    int n=30;
    int f[35][35];
    int g[35][35];
    int dir[5][2]= {{0,0},{0,1},{1,0},{-1,0},{0,-1}};
    void input()
    {
        for(int i=0; i<30; i++)
            scanf("%d",&g[i][30]);
    }
    void work()
    {
        int row,col;
        for(row=0,col=0; row<n&&col<n; col++)
        {
            int id=row;
            for(int i=id; i<n; i++)
                if(g[i][col])
                    id=i;
            if(g[id][col])
            {
                for(int k=col; k<=n; k++)
                    swap(g[row][k],g[id][k]);
                for(int i=row+1; i<n; i++)
                    if(g[i][col])
                        for(int k=col; k<=n; k++)
                            g[i][k]^=g[row][k];
                row++;
            }
        }
        //构建上三角完毕 下面开始回代过程
        for(int i=n-1;i>=0;i--)
        for(int j=n-1;j>i;j--)
        g[i][30]^=g[i][j]&&g[j][30];
        //这一行可以参考传统的求解过程来理解
    }
    void print()
    {
        for(int i=0; i<30; i++)
        {
            if((i+1)%6!=0)
                printf("%d ",g[i][30]);
            else
                printf("%d
    ",g[i][30]);
        }
    }
    void debug()
    {
        for (int i =0; i <30; i++)
        {
            for (int j =0; j <31; j++)
                cout <<""<< g[i][j];
            cout << endl;
        }
        cout << endl;
    }
    int main()
    {
        for(int i=0; i<5; i++)
            for(int j=0; j<6; j++)
                for(int k=0; k<5; k++)
                {
                    int a=i+dir[k][0];
                    int b=j+dir[k][1];
                    if(a>=0&&b>=0&&a<5&&b<6)
                        f[i*6+j][a*6+b]=1;
                }
        int t,cas=1;
        scanf("%d",&t);
        while(t--)
        {
            printf("PUZZLE #%d
    ",cas++);
            memcpy(g,f,sizeof(g));
            input();
            work();
            print();
        }
        return 0;
    }
  • 相关阅读:
    使用systemctl管理指定服务需要做的配置
    挖矿病毒
    灰度发布系统
    血一般的教训,请慎用insert into select
    关于程序bug的闲谈
    来自一个网络监控软件的自述
    为什么CTO、技术总监、架构师都不写代码,还这么牛逼?
    原来 Elasticsearch 还可以这么理解
    爬了20W+条猫咪交易数据,它不愧是人类团宠
    NPUCTF2020 这是什么觅🐎
  • 原文地址:https://www.cnblogs.com/Ritchie/p/5836923.html
Copyright © 2011-2022 走看看