话说好久没更博了。
最近学了好多知识懒的加进来了。
有幸认识一位大佬。
让我有了继续更博的兴趣。
但这是一个旧的题解。
我在某谷上早就发过的。
拿过来直接用就当回归了吧。
其实这道题有一个特别关键的思路。
拿着你要确定的魔板中列去枚举要匹配的魔板的每一列。
因为列是可以交换的。
而且还有最关键的一个点。
如果你确定了其中有一列对应了,那么你的魔板其实就已经固定了。行就不能变换了。
上边这个关键点的确不好想,但是想通了这个题也就好解决了。
然后就可以用map进行对应开始查询。
如果手里的魔板的数和要确定了一一对应了就YES了。
然后你手里的魔板和需要对应的魔板对应成功就可以输出YES了。
要记着在每次枚举的时候clear一次。
具体看下面代码。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cctype>
#include<map>
#define rg register
#define int long long
using namespace std;
inline int read(){
rg int s=0,f=0;
rg char ch=getchar();
while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
while(isdigit(ch)) s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
return f?-s:s;
}
int n,m,k;
const int MAX=115;
int a1[MAX][MAX],a2[MAX][MAX],vis[MAX];
string S;
map<string,int>hsh;
void init(){
n=read(),m=read();
for(rg int i=1;i<=n;++i){
for(rg int j=1;j<=m;++j){
a1[i][j]=read();
}
}
for(rg int i=1;i<=n;++i){
for(rg int j=1;j<=m;++j){
a2[i][j]=read();
}
}
}
signed main(){
k=read();
++k;
while(--k){
bool flag=0;
init();//初始化。
for(rg int i=1;i<=m;++i){
hsh.clear();//每次都要清空。
for(rg int j=1;j<=n;++j){
vis[j]=(a1[j][1]==a2[j][i])?0:1;
}//枚举是否能够对应。
for(rg int j=1;j<=n;++j){
for(rg int k=1;k<=m;++k){
a1[j][k]^=vis[j];
}
}//对应就可以^1(代表翻转过了)。
for(rg int j=1;j<=m;++j){
string s=S;
for(rg int k=1;k<=n;++k){
s+=(char)(a1[k][j]+'0');
}
++hsh[s];
}//转换成字符串。
for(rg int j=1;j<=n;++j){
for(rg int k=1;k<=m;++k){
a1[j][k]^=vis[j];
}
}//还原
for(rg int j=1;j<=m;++j){
string s=S;
for(rg int k=1;k<=n;++k){
s+=(char)(a2[k][j]+'0');
}
if(!hsh[s]) break;//这里没被改过就跳过。
--hsh[s];
if(j==m) flag=1;
}
}
if(flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}