分析

题意

给出 \(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;
}

posted on 2021-10-19 08:16  漠寒·  阅读(69)  评论(0编辑  收藏  举报