zoukankan      html  css  js  c++  java
  • 7305. 【2021.10.16NOIP提高组模拟】厜蓧篈壻鑨

    Description

    (1le n,mle 1000)

    Solution

    下面将 "#" 认为是 1,"." 认为是 0。

    可以发现答案是具有二分性的。因此考虑二分答案。

    对于答案 (x),先找出在 (x) 步内向外扩展不会到达的 0 的 1。

    然后把这些点加入队列,然后 ( ext{bfs}),看看经过 (x) 轮之后的形状是否与题目一样。

    至于如何找出最先加入队列的 1,我们可以先预处理出每个 1 到 0 的距离,然后找那些距离大于 (x) 的 1。

    Code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 1005
    using namespace std;
    int n,m,l,r,mid,ans,a[N][N],c[N][N],d[N*N][4];
    int fx[5]={0,1,-1,0,0},fy[5]={0,0,0,1,-1};
    bool b[N][N];
    char ch;
    bool check(int x)
    {
    	int h=0,t=0;
    	memset(d,0,sizeof(d));
    	memset(b,false,sizeof(b));
    	for (int i=1;i<=n;++i)
    		for (int j=1;j<=m;++j)
    		{
    			if (c[i][j]>x)
    			{
    				d[++t][1]=i;
    				d[t][2]=j;
    				d[t][3]=x;
    				b[i][j]=true;
    			}
    		}
    	while (h<=t)
    	{
    		int x=d[++h][1],y=d[h][2],z=d[h][3];
    		for (int i=1;i<=4;++i)
    		{
    			int xx=x+fx[i],yy=y+fy[i];
    			if (a[xx][yy]&&!b[xx][yy])
    			{
    				b[xx][yy]=true;
    				if (z-1)
    				{
    					d[++t][1]=xx;
    					d[t][2]=yy;
    					d[t][3]=z-1;
    				}
    			}
    		}
    	}
    	for (int i=1;i<=n;++i)
    		for (int j=1;j<=m;++j)
    			if (a[i][j]&&!b[i][j]) return false;
    	return true;
    }
    int main()
    {
     	freopen("1ysa93e.in","r",stdin);
     	freopen("1ysa93e.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	ch=getchar();
    	for (int i=1;i<=n;++i)
    	{
    		while (ch!='.'&&ch!='#') ch=getchar();
    		for (int j=1;j<=m;++j)
    		{
    			if (ch=='#') a[i][j]=1;
    			ch=getchar();
    		}
    	}
    	int h=0,t=1;
    	for (int i=1;i<=n;++i)
    		for (int j=1;j<=m;++j)
    			if (a[i][j]&&!(a[i][j-1]&&a[i][j+1]&&a[i-1][j]&&a[i+1][j])) c[i][j]=1,d[t][1]=i,d[t][2]=j,++t;
    	while (h<=t)
    	{
    		int x=d[++h][1],y=d[h][2];
    		for (int i=1;i<=4;++i)
    		{
    			int xx=x+fx[i],yy=y+fy[i];
    			if (a[xx][yy]&&!c[xx][yy])
    			{
    				d[++t][1]=xx;
    				d[t][2]=yy;
    				c[xx][yy]=c[x][y]+1;
    			}
    		}
    	}
    	l=1;r=min(n,m);
    	while (l<=r)
    	{
    		mid=(l+r)>>1;
    		if (check(mid)) ans=mid,l=mid+1;
    		else r=mid-1;
    	}
    	printf("%d
    ",ans);
    	return 0;
    } 
    
  • 相关阅读:
    Android手机 Fildder真机抓包
    android显示当前时间
    SlidingMenu实现app侧滑功能
    Android 带checkbox的listView 实现多选,全选,反选
    android记住密码和自动登陆
    判断是否第一次进入系统
    #10002 喷水装置
    Codeforces Round #503 (by SIS, Div. 2) C. Elections (暴力+贪心)
    P2024 [NOI2001] 食物链
    P2814 家谱
  • 原文地址:https://www.cnblogs.com/Livingston/p/15426161.html
Copyright © 2011-2022 走看看