牛客练习赛31 A题----地、颜色、魔法

本文详细解析了一道算法竞赛题目,关于如何在一个nxm的矩形地图上,根据特定规则计算可以被赋予颜色的位置数量。通过深度优先搜索算法,对地图边界可达性和标记点进行了深入探讨。

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

链接:https://ac.nowcoder.com/acm/contest/218/A
来源:牛客网

题目描述

红色来源于山脉,象征着狂躁、愤怒、混乱,血雨腥风,电光火石。
蓝色来源于海岛,象征着控制、幻觉、诡计,运筹帷幄,谋定后动。
绿色来源于树林,象征着生命、蛮力、成长,横冲直撞,生生不息。
黑色来源于沼泽,象征着死亡、贪婪、腐败,追求卓越,不计代价。
白色来源于平原,象征着秩序、公平、正义,携手共进,稳中求胜。

 

       现在,你作为一名新星鹏洛客,找到了一块绝佳的修炼地。这块地方可以被描述成一个 n x m 的矩形。你已经在这块地中的一些位置打好了标记。接下去,就该对整块地赋予你的颜色了。一个位置能被赋予你的颜色,当且仅当满足以下条件之一:
       1. 这个位置被打上了标记。
       2. 这个位置在不经过被打标记的位置的情况下与边界不连通(这个图是四联通的)。换句话说,如果你从这个位置开始,在不经过被打标记的位置,且只能向上下左右四个方向移动的情况下永远不能走到地图的边界,那么这个位置符合条件。
       现在,你的好基友想知道,你能为多少个位置赋予你自己的颜色呢?

输入描述:

第一行包含两个正整数 n, m ,表示地图的长和宽。
接下去 n 行,每行一个长为 m 的字符串,表示地图的一行。
其中  表示该位置未被打标记; 表示该位置被打了标记。
保证地图仅由  和  构成。

输出描述:

输出仅一行,包含一个整数,表示你的答案。

示例1

输入

复制

4 4
....
.###
.#.#
.###

输出

复制

9

说明

 

可以被赋予颜色的位置在下图中用  标出了。

\texttt{....}
\texttt{.@@@}
\texttt{.@@@}
\texttt{.@@@}

备注:

1 ≤ n x m ≤ 106

从边界点开始往里深搜,每走到一个点对该点进行加1,最后统计哪些点没有进行加1,则是答案。特别注意的是,数据量太大,可以把输入数据的每一行当作一个char数组,并将每一行每一个字符做标记后存进vector容器数组里,直接对vector数组进行搜索、标记和统计。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};
vector<int>mp[maxn];//数据量太大,则用vector容器代替二维数组 
int n, m;
int tot = 0;
void init(){
  for(int i = 0; i < maxn; i++)
    mp[i].clear();
  tot = 0;
}
bool judge(int i, int j) {
  if(i == 0 || i == n-1 || j == 0 || j == m-1) return true;
  return false;
}
void dfs(int i, int j) {
  if(mp[i][j] == 0 || mp[i][j] > 1) return;//该点为'#'或者有边界走到过该点了,则可以不用搜该点下面的路了直接返回 
  mp[i][j]++;//对k从边界可以走到的点都进行加一,走到了才能加一,不能先加一再走,否则上面的终止判断会出错 
  for(int k = 0; k < 4; k++) {
    int xx = i + dx[k];
    int yy = j + dy[k];
    if(xx >= 0 && xx < n && yy >= 0 && yy < m) dfs(xx, yy);
  }
}
int main() {
  while(scanf("%d%d",&n, &m) != EOF) {
    init();
    char c[maxn];
    for(int i = 0; i < n; i++) {
      scanf("%s", c);
      for(int j = 0; j < m; j++) {
        if(c[j] == '.' ) mp[i].push_back(1);
        else
          mp[i].push_back(0);
      }
    }
    for(int i = 0; i < n; i++) {
      for(int j = 0; j < m; j++) {
        if(mp[i][j] && judge(i, j)) dfs(i,j);//只对边界上的.进行搜索 
      }
    }
    for(int i = 0; i < n; i++) 
      for(int j = 0; j < m; j++)
        if(mp[i][j] > 1)tot++;//大于1的点,表示由边界出发可以走到的点,也就是可以到达边界的点 
    printf("%d\n", n*m-tot);
  }
  return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值