zoukankan      html  css  js  c++  java
  • 洛谷P1275 魔板

    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
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<map>
    #include<queue>
    #define maxn 110
    #define mod 10000003
    using namespace std;
    map<string,bool>vis;
    int n,m,T,a[10001];
    string t;
    string s,cur,nxt;
    queue<string>q;
    string hash(int x[]){
        string res="";
        for(int i=1;i<=n*m;i++)res+=x[i]+'0';
        return res;
    }
    bool bfs(){
        while(!q.empty()){
            cur=q.front();q.pop();
            for(int i=1;i<=n;i++){//枚举修改每一行 
                int w=(i-1)*m;
                nxt=cur;
                for(int j=0;j<m;j++){
                    if(nxt[w+j]=='0')nxt[w+j]='1';
                    else nxt[w+j]='0';
                }
                if(nxt==t)return 1;
                if(!vis[nxt]){
                    q.push(nxt);
                    vis[nxt]=1;
                }
            }
            for(int i=0;i<m;i++){//枚举修改每一列 
                nxt=cur;
                for(int j=0;j<m;j++){
                    if(nxt[i+j*m]=='0')nxt[i+j*m]='1';
                    else nxt[i+j*m]='0';
                }
                if(nxt==t)return 1;
                if(!vis[nxt]){
                    q.push(nxt);
                    vis[nxt]=1;
                }
            }
        }
        return 0;
    }
    int main(){
        scanf("%d",&T);
        while(T--){
            while(!q.empty())q.pop();
            s="";t="";
            //memset(vis,0,sizeof(vis));
            vis.clear();
            scanf("%d%d",&n,&m);
            for(int i=0;i<n*m;i++){
                scanf("%d",&a[i]);
                s+=a[i]+'0';
            }
            for(int i=0;i<n*m;i++){
                scanf("%d",&a[i]);
                t+=a[i]+'0';
            }
            vis[s]=1;
            q.push(s);
            if(bfs())printf("YES
    ");
            else printf("NO
    ");
        }
    }
    0分 手模不出样例,我自己写的宽搜也没过
    /*
        第一步:在最外层循环枚举初始的每一列当做目标状态的第一列
        第二步:在每层循环中比较当前这列和目标状态的第一列的同行的数,如果不相同则把初始的那一行翻转(前面先记录,后面记得还原)
        第三步:看看剩下的列是否可以一一对应,如果可以就yes,不可以就继续枚举。
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define maxn 110
    int n,m,T,s[maxn][maxn],t[maxn][maxn];
    bool change_x[maxn],vis_y[maxn];
    bool check(int x){
        memset(change_x,0,sizeof(change_x));
        memset(vis_y,0,sizeof(vis_y));
        for(int i=1;i<=n;i++)
            if(s[i][x]!=t[i][1])
                change_x[i]=1;//第i行需要翻转 
        vis_y[x]=1;
        for(int i=2;i<=m;i++){//目标状态的第i列 
            bool flag=0;
            for(int j=1;j<=m;j++){//初始状态的第j列 
                if(vis_y[j])continue;
                int cnt=0;
                for(int k=1;k<=n;k++){
                    if((change_x[k]&&s[k][j]!=t[k][i])||(!change_x[k]&&s[k][j]==t[k][i]))cnt++;
                    else break;
                }
                if(cnt==n){
                    vis_y[j]=1,flag=1;
                    break;
                }
            }
            if(!flag)return 0;
        }
        return 1;
    }
    int main(){
        freopen("Cola.txt","r",stdin);
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    scanf("%d",&s[i][j]);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    scanf("%d",&t[i][j]);
            bool flag=0;
            for(int i=1;i<=m;i++){//枚举初始状态的每一列与目标状态对应 
                int now=check(i);
                if(now==1){
                    printf("YES
    ");
                    flag=1;break;
                }
            }
            if(!flag)printf("NO
    ");
        }
    }
    100分
  • 相关阅读:
    点击空白处隐藏盒子
    java缓存技术
    使用Java处理大文件
    java实现把一个大文件切割成N个固定大小的文件
    笔记:Java的IO性能调整
    NIO之轻松读取大文件
    java读写文件,读超大文件
    java读取大文件 超大文件的几种方法
    java web服务器cpu占用过高的处理
    软件开发各类文档模板
  • 原文地址:https://www.cnblogs.com/thmyl/p/7593307.html
Copyright © 2011-2022 走看看