分析
题意
给出 \(n\),\(m\),\(k\),给出一个大小为 \(nm\) 的矩形。矩形仅包含 " * " 和 " . "。需要你用任意个仅包含 " * " 的开口向上 v 形结构,两边斜率为1,且边长严格大于 \(k\)(包含交点),来包含所有矩形的 " * "。
做法
用 \(vis(i,j)\) 表示第 \(i\) 第 \(j\) 列有没有被涵盖。
枚举每一个点作为 "V" 的交点,尽可能地延伸,即尽量地去找更长的满足条件的边,如果长度小于 \(k\) 就找到不为 " * " 的点,就不更新,否则就一直往上找,不断地更新 \(vis\) 数组。最后判断所有需涵盖是否全部涵盖就行了。
代码
#include<bits/stdc++.h>
using namespace std;
inline void read(int &res){
res=0;
int f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')res=(res<<1)+(res<<3)+c-48,c=getchar();
res*=f;
}
int mp[25][25];
int vis[25][25];
int T;
int n,m,k;
char c[25];
inline int check(int x,int y){//是否满足基础条件时就会越位
if(x-k+1<=0||y-k+1<=0||y+k-1>m)return 0;
return 1;
}
inline int dcheck(int x,int y){//检查是否能至少延伸出k+1的长度
for(int i=x,j=y,l=y,t=1;t<=k;i--,j--,l++,t++){
if(!mp[i][j]||!mp[i][l])return 0;
}
return 1;
}
signed main()
{
read(T);
while(T--){
memset(vis,0,sizeof(vis));
read(n);read(m);read(k);
k++;
for(int i=1;i<=n;i++){
scanf("%s",c+1);
for(int j=1;j<=m;j++){
if(c[j]=='*')mp[i][j]=1;
else mp[i][j]=0;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(!check(i,j))continue;
if(!dcheck(i,j))continue;
int x=i,y=j,l=j,t=1;
for(;t<=k;x--,y--,l++,t++){//先处理k+1
vis[x][y]=vis[x][l]=1;
}
for(;x>=1;x--,y--,l++,t++){//再尽可能改
if(!mp[x][y]||!mp[x][l])break;
vis[x][y]=vis[x][l]=1;
}
}
}
int bo=0;
for(int i=1;i<=n;i++){
if(bo)break;
for(int j=1;j<=m;j++){
if(bo)break;
if(mp[i][j]&&(!vis[i][j])){//需要改却未改
bo=1;
}
}
}
if(bo)puts("NO");
else puts("YES");
}
return 0;
}