题目描述
构造
我们可以考虑顺序扫一遍鼎面。
每碰到一个1,一定只与铜模的第一个1匹配,然后尝试匹配,匹配失败就是NO,否则把被匹配位置赋为0。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=1000+10;
bool a[maxn][maxn],b[maxn][maxn];
int c[maxn*maxn][2];
int i,j,k,l,t,n,m,top,ca,x,y,x1,x2,y1,y2;
bool czy,emp;
int read(){
int x=0;
char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x;
}
char get(){
char ch=getchar();
while (ch!='0'&&ch!='1') ch=getchar();
return ch;
}
bool pd1(int j){
int i;
fo(i,1,y)
if (b[j][i]) return 0;
return 1;
}
bool pd2(int j){
int i;
fo(i,1,x)
if (b[i][j]) return 0;
return 1;
}
bool pd3(int x,int y){
if (x<1||x>n||y<1||y>m) return 0;
else return 1;
}
int main(){
ca=read();
while (ca--){
emp=1;
top=0;
n=read();m=read();x=read();y=read();
fo(i,1,n)
fo(j,1,m){
a[i][j]=get()-'0';
if (a[i][j]) emp=0;
}
fo(i,1,x)
fo(j,1,y)
b[i][j]=get()-'0';
x1=1;x2=x;y1=1;y2=y;
while (x1<=x&&pd1(x1)) x1++;
while (x2>x1&&pd1(x2)) x2--;
while (y1<=y&&pd2(y1)) y1++;
while (y2>y1&&pd2(y2)) y2--;
if (x1>x2){
if (emp) printf("YES\n");else printf("NO\n");
continue;
}
fo(i,x1,x2)
fo(j,y1,y2)
b[i-x1+1][j-y1+1]=b[i][j];
x=x2-x1+1;
y=y2-y1+1;
fo(i,1,x){
fo(j,1,y+1)
if (j>y||b[i][j]) break;
if (j<=y) break;
}
x1=i;y1=j;
fo(i,1,x)
fo(j,1,y)
if (b[i][j]){
c[++top][0]=i-x1;
c[top][1]=j-y1;
}
czy=1;
fo(i,1,n){
fo(j,1,m)
if (a[i][j]){
fo(k,1,top)
if (pd3(i+c[k][0],j+c[k][1])&&a[i+c[k][0]][j+c[k][1]]) a[i+c[k][0]][j+c[k][1]]=0;
else{
czy=0;
break;
}
if (!czy) break;
}
if (!czy) break;
}
if (czy) printf("YES\n");else printf("NO\n");
}
}