Educational Codeforces Round 5 C The Labyrinth DFS

本文介绍了一个编程问题的解决方案,该问题要求在给定地图中移除障碍物后找出最大的空地区域。文章详细阐述了使用深度优先搜索(DFS)的方法来计算连通区域的大小,并注意避免重复计数同一连通区域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给一个N*M的地图,其中’.’表示空地,’*’表示障碍物。问,如果把障碍物拿掉,最多可以变成一个多大的全是空地的联通块?
思路:很容易想到把障碍物拿掉之后联通块的大小,就是上下左右的联通块大小加起来再加上障碍物本身一个联通块。有一点要注意,如果上和左属于同一个联通块的时候,不要重复加。求联通块的大小可以用DFS,先DFS一遍找联通块的大小,再DFS一遍把联通块中每个块的大小都赋成前面DFS找到的结果。
坑点:结果要% 10,当时没看到这点,WA了一发。

http://codeforces.com/contest/616/problem/C

/*********************************************
    Problem : Codeforces
    Author  : NMfloat
    InkTime (c) NM . All Rights Reserved .
********************************************/

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

#define rep(i,a,b)  for(int i = (a) ; i <= (b) ; i ++) //遍历
#define rrep(i,a,b) for(int i = (b) ; i >= (a) ; i --) //反向遍历
#define repS(it,p) for(auto it = p.begin() ; it != p.end() ; it ++) //遍历一个STL容器
#define repE(p,u) for(Edge * p = G[u].first ; p ; p = p -> next) //遍历u所连接的点
#define cls(a,x)   memset(a,x,sizeof(a))
#define eps 1e-8

using namespace std;

const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e5+5;
const int MAXE = 2e5+5;

typedef long long LL;
typedef unsigned long long ULL;

int T,n,m,k;

int fx[] = {0,1,-1,0,0};
int fy[] = {0,0,0,-1,1};

char Map[1005][1005];
int num[1005][1005];//每个点最多连接的点数.
bool vis[1005][1005];
bool vis1[1005][1005];
int belong[1005][1005];
int tot ;
int idx ;

void input() { 
    rep(i,1,n) scanf("%s",&Map[i][1]);
}

void dfs(int x,int y) {
    belong[x][y] = idx;
    tot ++;
    rep(i,1,4) {
        int tmpx = x + fx[i];
        int tmpy = y + fy[i];
        if(tmpx >= 1 && tmpx <= n && tmpy >= 1 && tmpy <= m && !vis[tmpx][tmpy]) {
            vis[tmpx][tmpy] = true;
            if(Map[tmpx][tmpy] == '.') {
                dfs(tmpx,tmpy);
            }
        }
    }
}

void dfs1(int x,int y) {
    num[x][y] = tot;
    rep(i,1,4) {
        int tmpx = x + fx[i];
        int tmpy = y + fy[i];
        if(tmpx >= 1 && tmpx <= n && tmpy >= 1 && tmpy <= m && !vis1[tmpx][tmpy]) {
            vis1[tmpx][tmpy] = true;
            if(Map[tmpx][tmpy] == '.') {
                dfs1(tmpx,tmpy);
            }
        }
    }
}

void solve() {
    cls(num,0); cls(vis,0); cls(vis1,0);
    cls(belong,0);
    idx = 0;
    rep(i,1,n) {
        rep(j,1,m) {
            if(!vis[i][j] && Map[i][j] == '.') {
                idx ++; tot = 0;
                vis[i][j] = true;
                vis1[i][j] = true;
                dfs(i,j);
                dfs1(i,j);
            }
        }
    }
    int x[6],y[6];
    int ans ;
    rep(i,1,n) {
        rep(j,1,m) {
            if(Map[i][j] == '.') printf(".");
            else {
                ans = 0;
                rep(ia,1,4) {
                    x[ia] = i + fx[ia];
                    y[ia] = j + fy[ia];
                }
                rep(ia,1,4) {
                    int ok1 = 0;
                    rep(ib,1,ia-1) {
                        if(belong[x[ia]][y[ia]] == belong[x[ib]][y[ib]]) ok1 = 1;
                    }
                    if(!ok1) ans += num[x[ia]][y[ia]]; 
                }
                printf("%d",(ans+1)%10);
            }
        }
        puts("");
    }
}

int main(void) {
    //freopen("a.in","r",stdin);
    while(~scanf("%d %d",&n,&m)) {
        input();
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值