链接:https://ac.nowcoder.com/acm/contest/218/A
来源:牛客网
题目描述
红色来源于山脉,象征着狂躁、愤怒、混乱,血雨腥风,电光火石。
蓝色来源于海岛,象征着控制、幻觉、诡计,运筹帷幄,谋定后动。
绿色来源于树林,象征着生命、蛮力、成长,横冲直撞,生生不息。
黑色来源于沼泽,象征着死亡、贪婪、腐败,追求卓越,不计代价。
白色来源于平原,象征着秩序、公平、正义,携手共进,稳中求胜。
现在,你作为一名新星鹏洛客,找到了一块绝佳的修炼地。这块地方可以被描述成一个 n x m 的矩形。你已经在这块地中的一些位置打好了标记。接下去,就该对整块地赋予你的颜色了。一个位置能被赋予你的颜色,当且仅当满足以下条件之一:
1. 这个位置被打上了标记。
2. 这个位置在不经过被打标记的位置的情况下与边界不连通(这个图是四联通的)。换句话说,如果你从这个位置开始,在不经过被打标记的位置,且只能向上下左右四个方向移动的情况下永远不能走到地图的边界,那么这个位置符合条件。
现在,你的好基友想知道,你能为多少个位置赋予你自己的颜色呢?
输入描述:
第一行包含两个正整数 n, m ,表示地图的长和宽。 接下去 n 行,每行一个长为 m 的字符串,表示地图的一行。 其中 表示该位置未被打标记; 表示该位置被打了标记。 保证地图仅由 和 构成。
输出描述:
输出仅一行,包含一个整数,表示你的答案。
示例1
输入
复制
4 4 .... .### .#.# .###
输出
复制
9
说明
可以被赋予颜色的位置在下图中用 标出了。
备注:
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;
}