有这样一种魔板:它是一个长方形的面板,被划分成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 <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <bitset>
#include <stack>
#define ll long long
#define ull unsigned long long
#define inf 0x3f3f3f3f
const int mod=1000000007;
const int N=105;
using namespace std;
int mp[N][N],ed[N][N];
int aa[N][N];
int vis[N];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
int flag=0,num;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
scanf("%d",&mp[i][j]);
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
scanf("%d",&ed[i][j]);
for(int k=1; k<=m; k++)//枚举每一列
{
memset(vis,0,sizeof(vis));
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
aa[i][j]=mp[i][j];
for(int i=1; i<=n; i++)
{
if(aa[i][k]!=ed[i][1])//每一列都和目标状态的第一列比较,不一样就0 1 转换
{
for(int j=1; j<=m; j++)
aa[i][j]=!aa[i][j];
}
}
vis[1]=1;
num=1;
for(int i=1; i<=m; i++)
{//遍历aa所有列,比较剩余的和目标是不是完全匹配
if(i!=k)
{ int f=0;
for(int j=2; j<=m; j++)//遍历目标状态的除第一列以外的列
{
if(!vis[j])
{
int ok=0;
for(int h=1; h<=n; h++)//行
{
if(ed[h][j]!=aa[h][i])//有不匹配的
{
ok=1;
break;
}
}
if(ok)
continue;
else//有匹配的
{
// f=1;
vis[j]=1,num++;
}
}
// if(f)
// break;
}
}
}
if(m==num)
{
printf("YES\n");
flag=1;
break;
}
}
if(!flag)
printf("NO\n");
}
return 0;
}