CF1579C题解

思路

依次枚举每一个黑色点,然后一枚举到的点为勾最靠下的那个点,如图种红色圈的部分。

然后搜索左上角和右上角,判断是否合法,即连续格子长度符合要求。

因为他的连续格子长度不一定是 \(d\),而长度越长是对其他勾没有影响,而覆盖的越多一定不或更差,所以我们就想要这个连续格子长度尽量长。而两边长度需要对称,所以取最小的一边。这个操作可以在判断时求。

如果判断合法,则把这个勾能够染成黑色的格子标记。

最后看一下是不是所有黑色格子都被标记过就好了。

AC CODE

#include<bits/stdc++.h>
using namespace std;
int n,m,d,dx[4]={-1,-1,1,1},dy[4]={-1,1,-1,1},vis[20][20],vis2[20][20],minn=1e9;
char c[20][20];
bool dfs(int x,int y,int f,int t){//左上角或右上角方向染色格子长度是否大于等于d
	x+=dx[f];
	y+=dy[f];
	if(vis[x][y]==0){
		if(t<d)return false;
		minn=min(minn,t);
		return true;
	}
	if(x<1||y<1||y>m)return false; 
	dfs(x,y,f,t+1);
}
void dfs2(int x,int y,int f,int t){//标记勾能染到的格子
	if(t>minn)return;
	vis2[x][y]=1;
	x+=dx[f];
	y+=dy[f];
	dfs2(x,y,f,t+1);
}
int main(){
	int T;
	cin>>T;
	while(T--){
		memset(vis,0,sizeof vis);
		memset(vis2,0,sizeof vis2);
		cin>>n>>m>>d;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cin>>c[i][j];
				if(c[i][j]=='*')vis[i][j]=1;
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(vis[i][j]){
					minn=1e9;
					if(dfs(i,j,0,0)&&dfs(i,j,1,0)){//判断
						vis2[i][j]=1;//标记
						dfs2(i,j,0,0);
						dfs2(i,j,1,0);
					}
				}	
			}
		}
		bool ok=1;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(c[i][j]=='*'){//所有黑色格子是否被标记
					if(!vis2[i][j])ok=0;
				}
			}
		} 
		if(ok)cout<<"YES";
		else cout<<"NO";
		cout<<endl;
	}
	return 0;
}
posted @ 2024-01-15 22:22  Xu_dh  阅读(64)  评论(0)    收藏  举报