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。(注意:请使用大写字母)

    输入输出样例

    输入样例#1: 
    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
    输出样例#1: 
    YES
    NO
    

    Solution:

      本题其实没有想象的那么难(主要是我开始受到刚做的另一道叫魔板的题目影响,下意识的想怎么去判重存状态去了,结果感觉不可做),实际上直接暴力模拟就可以了。

      首先可以确定的是无论怎么操作,每一行的$1$的个数都只有两种情况(要么是本来的$1$的个数,要么是$0$的个数),所以操作$1$对于每行来说最多进行一次,当行中的$0,1$都确定不变后,那么要使初始状态$st$变换到目标状态$ed$就是操作$2$了。

      于是一个很简单的思路就出来了:

      1、先判断$st$的每行$1$的个数是否可以变到$ed$中的每行$1$的个数,若不行直接输出$NO$,可以变换再枚举。

      2、首先枚举$st$的每一列来做为转移时中间状态的第$1$列,通过操作$1$使得其和目标状态的第$1$列相同,之后就只需用到操作$2$,依次枚举剩下的列中和目标状态第$2$列、第$3$列…一直往下(记得当两列相同后,要在中间状态中通过操作$2$移动该列到匹配的位置,否则往后枚举可能会出现列重复使用的情况),当某列无法和目标状态匹配时,直接跳出循环,说明该中间状态不行。

      具体实现,详见代码。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long 
    using namespace std;
    const int N=105;
    int st[N][N],ed[N][N],tmp[N][N],n,m,k,hang1[N],hang2[N];
    bool vis[N],f,hang[N],lie[N];
    il int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
        return f?-a:a;
    }
    il void change1(int x[][N],int k){
        for(int i=1;i<=m;i++)x[k][i]=1-x[k][i];
    }
    il void change2(int x[][N],int s,int t){
        for(int i=1;i<=n;i++)swap(x[i][s],x[i][t]);
    }
    il bool check(int s[][N],int t[][N],int l1,int l2){
        for(int i=1;i<=n;i++)
            if(s[i][l1]!=t[i][l2])return 0;
        return 1;
    }
    il void init(){
        n=gi(),m=gi();f=0;
        memset(hang1,0,sizeof(hang1));
        memset(hang2,0,sizeof(hang2));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
            st[i][j]=gi();
            if(st[i][j]==1)hang1[i]++;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
            ed[i][j]=gi();
            if(ed[i][j]==1)hang2[i]++;
            }
            if(hang1[i]!=hang2[i]&&hang1[i]!=m-hang2[i])f=1;
        }
        if(f){puts("NO");return;}
        for(int p=2;p<=m;p++){
            memcpy(tmp,st,sizeof(st));
            change2(tmp,1,p);
            for(int i=1;i<=n;i++)
                if(tmp[i][1]!=ed[i][1])change1(tmp,i);
            for(int i=1;i<=m;i++){
                f=0;
                for(int j=i;j<=m;j++)
                if(check(tmp,ed,j,i)){change2(tmp,i,j);f=1;break;}
                if(!f)break;
            }
            if(f)break;
        }
        if(f){puts("YES");return;}
        puts("NO");
    }
    int main(){
        k=gi();
        while(k--){
            init();
        }
        return 0;
    }
  • 相关阅读:
    使用NBU进行oracle异机恢复
    mycat偶尔会出现JVM报错double free or corruption并崩溃退出
    exp导出数据时丢表
    service_names配置不正确,导致dg创建失败
    XML概念定义以及如何定义xml文件编写约束条件java解析xml DTD XML Schema JAXP java xml解析 dom4j 解析 xpath dom sax
    HTTP协议简介详解 HTTP协议发展 原理 请求方法 响应状态码 请求头 请求首部 java模拟浏览器客户端服务端
    java集合框架容器 java框架层级 继承图结构 集合框架的抽象类 集合框架主要实现类
    【JAVA集合框架一 】java集合框架官方介绍 Collections Framework Overview 集合框架总览 翻译 javase8 集合官方文档中文版
    java内部类深入详解 内部类的分类 特点 定义方式 使用
    再谈包访问权限 子类为何不能使用父类protected方法
  • 原文地址:https://www.cnblogs.com/five20/p/8909094.html
Copyright © 2011-2022 走看看