题面
题意:给你两个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;
}