P7479 至曾是英雄的您

P7479 至曾是英雄的您(模拟,连通块)

其实可以围的条件就是:黑棋最多一个“真眼”。

于是考虑什么情况下一个联通块空地成为一个“真眼”:即不存在至少这样的一个点满足其四面都没有黑棋。

那么判断一下再染色,最后看有多少个连通块没有被染色即可。

代码:

#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
	x=0;char ch=getchar();bool f=false;
	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	x=f?-x:x;
	return ;
}
template <typename T>
inline void write(T x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10^48);
	return ;
}
const int N=2e3+5; 
int n,m,T,x[6]={0,1,-1,0,0},y[6]={0,0,0,-1,1},num[N][N],tot;
char s[N][N];
bool vis[N][N];
inline bool Check(int X,int Y){return (X>=1&&Y>=1&&X<=n&&Y<=m);}
inline bool CheckPut(int X,int Y){
	for(int i=1;i<=4;i++) if(num[X+x[i]][Y+y[i]]!=1) return false;
	return true; 
}
void dfs(int nx,int ny){
	vis[nx][ny]=true;
	for(int i=1;i<=4;i++){
		int fx=nx+x[i],fy=ny+y[i];
		if(!Check(fx,fy)) continue;
		if(!vis[fx][fy]) dfs(fx,fy);
	}
	return ;
}
int main(){
	read(T);
	while(T--){
		read(n),read(m);
		tot=0;
		for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
		for(int i=0;i<=n+1;i++){
			for(int j=0;j<=m+1;j++){
				num[i][j]=1;vis[i][j]=false;
				if(s[i][j]=='*') num[i][j]=0,vis[i][j]=true;
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(s[i][j]!='*'){
					if(vis[i][j]) continue;
					if(CheckPut(i,j)) dfs(i,j); 
				}
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(!vis[i][j]) tot++,dfs(i,j);
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				s[i][j]=' ';
			}
		}
		if(tot<=1) puts("NO");
		else puts("YES");
		
	}
	return 0;
}
posted @ 2021-04-16 16:11  __Anchor  阅读(82)  评论(0编辑  收藏  举报