zoukankan      html  css  js  c++  java
  • 【洛谷】P1275 魔板(暴力&思维)

    题目描述

      有这样一种魔板:它是一个长方形的面板,被划分成n行m列的n*m个方格。每个方格内有一个小灯泡,灯泡的状态有两种(亮或暗)。我们可以通过若干操作使魔板从一个状态改变为另一个状态。操作的方式有两种:
      (1)任选一行,改变该行中所有灯泡的状态,即亮的变暗、暗的变亮;
      (2)任选两列,交换其位置。
      当然并不是任意的两种状态都可以通过若干操作来实现互相转化的。
      你的任务就是根据给定两个魔板状态,判断两个状态能否互相转化。

    输入格式

      文件中包含多组数据。第一行一个整数k,表示有k组数据。
      每组数据的第一行两个整数n和m。(0<n,m≤100)
      以下的n行描述第一个魔板。每行有m个数字(0或1),中间用空格分隔。若第x行的第y个数字为0,则表示魔板的第x行y列的灯泡为“亮”;否则为“暗”。
      然后的n行描述第二个魔板。数据格式同上。
      任意两组数据间没有空行。

    输出格式

      共k行,依次描述每一组数据的结果。
      若两个魔板可以相互转化,则输出YES,否则输出NO。(注意:请使用大写字母)

    输入输出样例

    输入
      2
      3 4
      0 1 0 1
      1 0 0 1
      0 0 0 0
      0 1 0 1
      1 1 0 0
      0 0 0 0
      2 2
      0 0
      0 1
      1 1
      1 1

    输出

      YES

      NO

    分析

      一直以为是个结论题没想到居然是个暴力枚举的。。。。。。

      先来手玩一下就可以发现(并不,所以每行最多只有可能变换一次,不然就换回来了。

      所以每一行就会有两种情况,变和不变

      然后yyq暴力2^n枚举每行的变化情况加剪枝大力出奇迹过了这个题

     

      其实除了2^n枚举之外,还有一种枚举方法

      对于每一列来说,列的变换不会改变数字

      先假设能成功

      那么如果我们知道第1个矩阵中的某一列经过变换后成为第2个矩阵的某一列,

      那我们就可以通过比较两个列哪些数字不同,推出哪些行是变换了的

      所以我们直接去枚举第1个矩阵中的第一列经过变换后成为第2个矩阵的第i列

      然后推出哪些行是变换了,进而n^3判断剩下的列是否可行。

      如果全都不行则无解

      复杂度是O(kn^4),开开O2应该可以过

      我不信你100张牌能秒我???(雾

      代码

    #include<cstdio>
    #include<cstring>
    int T,n,m,rev[105],vis[105],nw[105][105],nx[105][105];
    bool check(int x)
    {
        memset(vis,0,sizeof vis);vis[x]=1;
        for(int j=2;j<=m;j++)
        {
            int flag=0;
            for(int k=1;k<=m;k++)if(!vis[k])
            {
                flag=1;
                for(int i=1;i<=n;i++)flag&=(nw[i][j]==(rev[i]^nx[i][k]));
                if(flag){vis[k]=1;break;}
            }
            if(!flag)return 0;
        }
        return 1;
    }
    int main()
    {
        for(scanf("%d",&T);T;T--)
        {
            scanf("%d%d",&n,&m);int flag=0;
            for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&nw[i][j]);
            for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&nx[i][j]);
            for(int i=1;i<=m&&!flag;i++)
            {
                memset(rev,0,sizeof rev);
                for(int j=1;j<=n;j++)rev[j]=(nw[j][1]!=nx[j][i]);
                flag=check(i);
            }
            if(flag)puts("YES");else puts("NO");
        }
    }   
  • 相关阅读:
    正则表达式实现密码检查
    用ueditor上传图片、文件等到七牛云存储
    cas单点登录流程
    移动端 触摸事件 ontouchstart、ontouchmove、ontouchend、ontouchcancel
    新开博客
    深入理解Mysql数据库主从延迟
    js 关于下载文件如何判断是否下载成功
    [我还会回来的]asp.net core再战iris
    nrm的使用
    innodb_flush_log_at_trx_commit参数测试
  • 原文地址:https://www.cnblogs.com/firecrazy/p/11654590.html
Copyright © 2011-2022 走看看