codeforces679C Bear and Square Grid(dfs优化)

题意:

给你n*n的矩阵(n<=500),矩阵内有x和.,然后给你一个k

你可以把一个k*k的矩阵内全部变成.

问你最多有多少个.可以联通

思路:

n^2枚举炸的位置,先预处理联通块和区间.的和

每次向右枚举只需要删掉左边一列,加上右边一列

每次枚举的区间是k*k然后扩展一圈((k+2)*(k+2))去掉四个角

这些点所在的联通块都是可以连通的

每次把这些联通块加起来,加上k*k的矩阵,减去这个矩阵内原本的.数量(预处理过)

O(n^2*k)

/* ***********************************************
Author        :devil
Created Time  :2016/6/23 15:27:25
************************************************ */
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <stdlib.h>
using namespace std;
const int N=510;
char s[N][N];
int sum[N][N];
int mp[N*N];
int vis[N][N];
int cur,id,all,n,k;
int vsc[N*N];
void dfs(int x,int y)
{
    cur++;
    vis[x][y]=id;
    if(s[x-1][y]==‘.‘&&!vis[x-1][y]) dfs(x-1,y);
    if(s[x+1][y]==‘.‘&&!vis[x+1][y]) dfs(x+1,y);
    if(s[x][y-1]==‘.‘&&!vis[x][y-1]) dfs(x,y-1);
    if(s[x][y+1]==‘.‘&&!vis[x][y+1]) dfs(x,y+1);
}
void push(int x,int y)
{
    if(!vis[x][y]) return ;
    if(!vsc[vis[x][y]]) all+=mp[vis[x][y]];
    vsc[vis[x][y]]++;
}
void pop(int x,int y)
{
    if(!vis[x][y]) return ;
    vsc[vis[x][y]]--;
    if(!vsc[vis[x][y]]) all-=mp[vis[x][y]];
}
int cal(int x,int y)
{
    return sum[x][y]-sum[x-k][y]-sum[x][y-k]+sum[x-k][y-k];
}
int main()
{
    //freopen("in.txt","r",stdin);
    int ans=0;
    id=1;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%s",s[i]+1);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1];
            if(s[i][j]==‘.‘) sum[i][j]++;
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(s[i][j]==‘.‘&&!vis[i][j])
            {
                cur=0;
                dfs(i,j);
                mp[id++]=cur;
            }
    for(int i=1;i<=n-k+1;i++)
    {
        all=0;
        memset(vsc,0,sizeof(vsc));
        for(int j=i-1;j<=i+k;j++)
            for(int l=1;l<=k;l++)
                push(j,l);
        for(int j=i;j<i+k;j++)
            push(j,k+1);
        ans=max(ans,all+k*k-cal(i+k-1,k));
        for(int j=1;j<=n-k;j++)
        {
            for(int l=i;l<i+k;l++)
            {
                pop(l,j-1);
                push(l,j+k+1);
            }
            pop(i-1,j);
            pop(i+k,j);
            push(i-1,j+k);
            push(i+k,j+k);
            ans=max(ans,all+k*k-cal(i+k-1,j+k));
        }
    }
    printf("%d\n",ans);
    return 0;
}
时间: 2024-07-30 08:29:44

codeforces679C Bear and Square Grid(dfs优化)的相关文章

codeforces 680E Bear and Square Grid 巧妙暴力

这个题是个想法题 先预处理连通块,然后需要用到一种巧妙暴力,即0变1,1变0,一列列添加删除 复杂度O(n^3) #include <cstdio> #include <iostream> #include <ctime> #include <vector> #include <cmath> #include <map> #include <queue> #include <algorithm> #includ

CF679C(Bear and Square Grid) 经典好题

题目链接:传送门 题目大意:给你一个n*n包含".","X"的图,你有一次机会选择一个k*k的子矩阵,将子矩阵全部变为".",问当操作过后,得到的最大联通子块包含的"."的数目是多少. 题目思路:其实这个题自己只想到了一个暴力的思路,当然TLE没商量,但实际上正确的想法就是先dfs预处理所有"."的联通块,之后的想法技巧性太强了,        操作是模拟将子矩阵右移,直接暴力会TLE,而我们可以想到实际上

codeforces 356C Bear and Square Grid

#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> using namespace std; char mp[510][510]; int vis[510][510]; int are_num[510][510]; int sum[510][510]; int

hdu 1518 Square (dfs搜索可参考poj1011)

Square Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8589    Accepted Submission(s): 2784 Problem Description Given a set of sticks of various lengths, is it possible to join them end-to-end

HJDU 1518—— Square(DFS)

简单深搜~~~~ <strong>#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<functional> #define M 30 using namespace std; int vis[M],a[M],n,flag,sum; void dfs(int s,int cur,int d) { if(cur==3||fl

hdu4393Digital Square(dfs)

Digital Square Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1827 Accepted Submission(s): 714 Problem Description Given an integer N,you should come up with the minimum nonnegative integer M.M m

HDOJ 题目4394 Digital Square(DFS)

Digital Square Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1757    Accepted Submission(s): 677 Problem Description Given an integer N,you should come up with the minimum nonnegative integer

HDU1518 Square(DFS)

Square Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 11151    Accepted Submission(s): 3588 Problem Description Given a set of sticks of various lengths, is it possible to join them end-to-en

HDU 1518 Square (DFS+剪枝)

Given a set of sticks of various lengths, is it possible to join them end-to-end to form a square? Input The first line of input contains N, the number of test cases. Each test case begins with an integer 4 <= M <= 20, the number of sticks. M intege