您的位置:首页 > 其它

[POI 2015]Piecz(模拟)

2015-06-24 21:21 344 查看

题目链接

http://main.edu.pl/en/user.phtml?op=showtask&task=pie&con=OI22

题目大意

一张n*m的方格纸,有些格子需要印成黑色,剩下的格子需要保留白色。

你有一个a*b的印章,有些格子是凸起(会沾上墨水)的。你需要判断能否用这个印章印出纸上的图案。印的过程中需要满足以下要求:

(1)印章不可以旋转。

(2)不能把墨水印到纸外面。

(3)纸上的同一个格子不可以印多次。

对于每个测试点,输出TAK(是)或NIE(否)。

思路

我们找出印章里最左上角的凸起的点,记录下其他凸起的点和这个点之间的相对位置。然后再在方格纸里不断枚举需要被印刷的图案的左上角的黑点,每次枚举出一个黑点,就用之前所求的相对位置把附近的黑点标记为被染过色。反复这样做。这个过程中如果发现有不合法的情况,就说明无法给这个方格纸染色了

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 1100

using namespace std;

int n,m,a,b;
char mp[MAXN][MAXN],stamp[MAXN][MAXN];
pair<int,int>stack[MAXN*MAXN];
int top=0;
bool vis[MAXN][MAXN];
int T;

bool inMap(int i,int j)
{
if(i<=0||i>n||j<=0||j>m) return false;
if(vis[i][j]||mp[i][j]=='.') return false;
return true;
}

int main()
{
scanf("%d",&T);
while(T--)
{
top=0;
scanf("%d%d%d%d",&n,&m,&a,&b);
for(int i=1;i<=n;i++)
scanf("%s",mp[i]+1);
for(int i=1;i<=a;i++)
scanf("%s",stamp[i]+1);
int zsx=-1,zsy=-1; //印章左上角突起的点d坐标
for(int i=1;i<=a;i++)
for(int j=1;j<=b;j++)
{
if(stamp[i][j]=='x')
{
if(zsx==-1)
{
zsx=i;
zsy=j;
}
else
stack[++top]=make_pair(i-zsx,j-zsy);
}
}
if(zsx==-1)
{
printf("NIE\n");
continue;
}
memset(vis,0,sizeof(vis));
bool flag=false;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(mp[i][j]=='.'||vis[i][j]) continue;
vis[i][j]=true;
for(int k=1;k<=top;k++)
{
if(!inMap(i+stack[k].first,j+stack[k].second))
{
flag=true;
break;
}
vis[i+stack[k].first][j+stack[k].second]=true;
}
if(flag) break;
}
if(flag) break;
}
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
{
if(vis[i][j]==0&&mp[i][j]=='x')
{
flag=true;
break;
}
}
if(flag)
printf("NIE\n");
else printf("TAK\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: