zoukankan      html  css  js  c++  java
  • luogu P1275 魔板 题解

    题面
    题意:给你两个n×m的01矩阵,每次可以对其中一个矩阵进行交换两列,或者反转某一行(0变1,1变0)的 操作,问两个矩阵是否能互相转化。

    首先我们只考虑对第一个矩阵进行操作,让它变成第二个矩阵。
    我们考虑无论第一个矩阵如何变换,最终都需要有一列变得和第二个矩阵的第一列一样,而如果我们强制某一列变得和第二个矩阵的第一列一样的话,那么所有行上的异或操作的状态就确定了,这样我们就只需要将剩下的m-1列进行匹配就可以了。
    所以我们枚举每一列与第二个矩阵的第一列匹配,将不同的行全部反转,然后检查一下这m列能不能互相匹配。

    代码(另一种做法,将两个矩阵都变成子典序最小的状态,然后判断是否相同):

    #include<bits/stdc++.h>
    using namespace std;
    #define N 107
    char g[N][N];
    int n,m;
    void swp(int x,int y)
    {
    	for(int i=1;i<=n;i++)
    		swap(g[i][x],g[i][y]);
    }
    void chg(int x)
    {
    	for(int i=1;i<=m;i++)
    		g[x][i]^=1;
    }
    string s[N];
    string solve()
    {
    	string ret="";
    	for(int o=1;o<=m;o++)
    	{
    		swp(o,1);
    		for(int i=1;i<=n;i++)
    			if(g[i][1]=='1')chg(i);
    		for(int i=2;i<=m;i++)
    		{
    			s[i]="";
    			for(int j=1;j<=n;j++)
    				s[i]+=g[j][i];
    		}
    		sort(s+2,s+m+1);
    		string t="";
    		for(int i=2;i<=m;i++)
    			t+=s[i];
    		if(o==1)ret=t;
    		else ret=min(ret,t);
    	}
    	return ret;
    }
    int main()
    {
    	int T;
    	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("%s",&g[i][j]);
    		string s1=solve();
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=m;j++)
    				scanf("%s",&g[i][j]);
    		string s2=solve();
    		if(s1==s2)printf("YES
    ");
    		else printf("NO
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    JDOJ 2430: 组合数取模
    USACO Dual Palindromes
    洛谷 P1365 WJMZBMR打osu! / Easy
    洛谷 P6154 游走
    洛谷 P1654 OSU!
    洛谷 P3802 小魔女帕琪
    洛谷 P1784 数独
    POJ King Arthur's Birthday Celebration
    洛谷 P4550 收集邮票
    洛谷 SP1026 FAVDICE
  • 原文地址:https://www.cnblogs.com/lishuyu2003/p/12142459.html
Copyright © 2011-2022 走看看