Codeforces 679C Bear and Square Grid(枚举 标记)

给你n∗n的矩阵里面有.和X,然后你可以把一块k∗k的全部变成.  
问你一个连通块里最多有多少个. 
看着不太难的题,但是不太好搞 
首先是dfs预处理每个连通块里的.的个数 
然后是n2的枚举k∗k的那块,对于k∗k这块,肯定都是.,然后就是枚举(k+2)∗(k+2)的这块的四周 
去掉4个角,因为这四周和k∗k的相邻,然后看有多少个连通块,个数加进去 
最后扣掉在内部的 
思路感觉不难,但是不是很好实现,如何n3的枚举呢 
因为如果n2的枚举顶点,再k2的枚举里面的元素,就TLE了 
所以要枚举行,然后对每行的第一个k∗k的矩阵,里面的.保存 
然后列里变换,只需要减去左边一列,加上右边一列,这是n3的 
然后知道了变换,然后n的枚举列,n的枚举四周 
但是你不知道四周的连通块里有多少在内部 
所以开头枚举里面的元素的时候,就要保存在内部的元素,属于第几个连通块的有几个 

然后对于每个周围连着的连通块,ans+=all[i]−in[i] 


#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")

using namespace std;
#define   MAX           505
#define   MAXN          1000005
#define   maxnode       205
#define   sigma_size    2
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,LL>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
//const double pi    = acos(-1.0);
const double inf   = 1e18;
const double eps   = 1e-9;
const LL     mod   = 1e8+9;
const ull    mx    = 133333331;

/*****************************************************/
inline void RI(int &x) {
      char c;
      while((c=getchar())<'0' || c>'9');
      x=c-'0';
      while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
 }
/*****************************************************/


char s[505][505];
int dx[5]={0,1,0,-1};
int dy[5]={1,0,-1,0};
int sum[MAX*MAX];
int a[MAX][MAX];
int vis[MAX][MAX];
int vv[MAX*MAX];
int be[MAX][MAX];
int cnt[MAX*MAX];

void dfs(int x,int y,int c){
    be[x][y]=c;
    sum[c]++;
    vis[x][y]=1;
    for(int k=0;k<4;k++){
        int xx=x+dx[k];
        int yy=y+dy[k];
        if(a[xx][yy]==1&&!vis[xx][yy]) dfs(xx,yy,c);
    }
}

int main(){
    int n,K;
    while(cin>>n>>K){
        mem(a,0);mem(vis,0);mem(sum,0);
        for(int i=1;i<=n;i++){
            scanf("%s",s[i]+1);
            for(int j=1;j<=n;j++){
                if(s[i][j]=='.') a[i][j]=1;
            }
        }
        int c=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(a[i][j]==1&&!vis[i][j]){
                    c++;
                    dfs(i,j,c);
                }
            }
        }
        int ans=0;
        mem(vv,0);
        for(int i=1;i<=n-K+1;i++){
            mem(cnt,0);
            for(int j=i;j<i+K;j++){
                for(int k=1;k<=K;k++){
                    if(s[j][k]=='.') cnt[be[j][k]]++;
                }
            }
            for(int j=1;j<=n-K+1;j++){
                int temp=K*K;
                vector<int> tmp;
                for(int k=i;k<i+K;k++){
                    if(a[k][j-1]){
                        int xx=be[k][j-1];
                        if(!vv[xx]){
                            vv[xx]=1;
                            tmp.push_back(xx);
                        }
                    }
                    if(a[k][j+K]){
                        int xx=be[k][j+K];
                        if(!vv[xx]){
                            vv[xx]=1;
                            tmp.push_back(xx);
                        }
                    }
                }
                for(int k=j;k<j+K;k++){
                    if(a[i-1][k]){
                        int xx=be[i-1][k];
                        if(!vv[xx]){
                            vv[xx]=1;
                            tmp.push_back(xx);
                        }
                    }
                    if(a[i+K][k]){
                        int xx=be[i+K][k];
                        if(!vv[xx]){
                            vv[xx]=1;
                            tmp.push_back(xx);
                        }
                    }
                }
                for(int k=0;k<tmp.size();k++){
                    temp+=sum[tmp[k]]-cnt[tmp[k]];
                    vv[tmp[k]]=0;
                }
                ans=max(ans,temp);
                for(int k=i;k<i+K;k++){
                    if(a[k][j]) cnt[be[k][j]]--;
                    if(a[k][j+K]) cnt[be[k][j+K]]++;
                }
            }
        }
        cout<<ans<<endl;
    }
    return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值