【题意】
一张n*m的方格纸,有些格子需要印成黑色,剩下的格子需要保留白色。
你有一个a*b的印章,有些格子是凸起(会沾上墨水)的。你需要判断能否用这个印章印出纸上的图案。印的过程中需要满足以下要求:
(1)印章不可以旋转。
(2)不能把墨水印到纸外面。
(3)纸上的同一个格子不可以印多次。
0<=n,m,a,b<=1000。
【思路】
先将纸与印章的黑色点做成链表,然后从纸的最上面一行的最左边一个开始找,每找到要印的点就从印章的最上面一行的最左边一个对准了印,看看能不能印好。
【代码】
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 1100
struct node
{
int x,y;
}list[MAXN*MAXN],yz[MAXN*MAXN];
int len=0,yzlen=0,n,m,k,p,stx,sty;
char ss[MAXN];
bool a[MAXN][MAXN],b[MAXN][MAXN];
inline int read()
{
int ans=0,x,f=1;
while(1)
{
x=getchar();
if(x=='-')f=-1;
if(x>='0'&&x<='9')break;
}
while(x>='0'&&x<='9')
{
ans=ans*10+x-'0';
x=getchar();
}
return ans*f;
}
bool clear(node x)
{
for(int i=1;i<=yzlen;i++)
{
if(x.x+yz[i].x<=0||x.x+yz[i].x>n||x.y+yz[i].y<=0||x.y+yz[i].y>m)return false;
if(!a[x.x+yz[i].x][x.y+yz[i].y])return false;
a[x.x+yz[i].x][x.y+yz[i].y]=false;
}
return true;
}
int main()
{
int T=read();
while(T--)
{
memset(a,false,sizeof(a));
memset(b,false,sizeof(b));
len=0;yzlen=0;
n=read(),m=read(),k=read(),p=read();
for(int i=1;i<=n;i++)
{
scanf("%s",ss+1);
for(int j=1;j<=m;j++)
{
if(ss[j]=='x')
{
a[i][j]=true;
len++;
list[len].x=i;
list[len].y=j;
}
}
}
stx=sty=0;
for(int i=1;i<=k;i++)
{
scanf("%s",ss+1);
for(int j=1;j<=p;j++)
if(ss[j]=='x')
{
b[i][j]=true;
if(!stx)
{
stx=i;sty=j;
}
yzlen++;
yz[yzlen].x=i-stx;
yz[yzlen].y=j-sty;
}
}
bool ans=true;
for(int i=1;i<=len;i++)
if(a[list[i].x][list[i].y])
if(!clear(list[i]))
{
ans=false;
break;
}
if(ans)printf("TAK\n");
else printf("NIE\n");
}
return 0;
}