题目相关
题目链接
计蒜客,https://nanti.jisuanke.com/t/T1769。
我的OJ,http://47.110.135.197/problem.php?id=5253。
题目描述
蒜头君来到一座陌生的城市打工,他和几个朋友合租一个房子。房东给他们发来了户型图,这个房子非常大,而且布局很奇怪。具体来说,房子可以被看做一个 N×M 的矩形,有墙壁的地方被标记为'#'
,其他地方被标记为'.'
。通过'.'
连在一起的区域被称作房间,现在蒜头君想知道,一共有多少个房间。
输入格式
第一行包含两个整数,N 和 M。
接下来 N 行,每行包含 M 个字符描述房间的情况,只包含'#'
和'.'
。
输出格式
输出一个整数,表示房间的个数。
输入样例
3 3
#.#
#.#
.#.
输出样例
3
题目分析
题意分析
在一个 N×M 的矩形找出连通区域有几块。标准的 BFS 题目。
P.S.
本题是一个判断连通性问题,也可以使用查并集来解决。
样例数据分析
没什么特别需要分析的,套用 BFS 模板就可以了。
数据范围分析
鄙视一下出题人,没有给出明确的 N 和 M 的范围,搞得我 n+1 次段错误,最后经过测试得到 N, M ≤ 2000。
算法思路
核心就是从头到尾遍历矩阵,如果某个位置 (x,y),如果该点为 . ,而且没有被访问过,就以该点为起点进行一次 BFS,搜索完成房间数加一。一直到整个矩阵遍历完成。
这样的算法复杂度为 。根据最不利原则,在最坏的情况下,矩阵一半的房间,一半是墙壁,而且每个房间只有一个点。如下数据样例:
6 6
. # . # . #
# . # . # .
. # . # . #
# . # . # .
. # . # . #
# . # . # .
也就是说,最大的处理数据量为 2000*2000/2=2e6 的数据。
当前这个暴力搜索算法在计蒜客已经通过。
参考代码
暴力搜索代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2002;
const int MAXM = MAXN;
typedef struct _POS {
int x;
int y;
} POS;
typedef struct _ROOM {
int n;
int m;
char data[MAXN][MAXM];
bool vis[MAXN][MAXM];
} ROOM;
void bfs(ROOM &room, int x, int y) {
queue<POS> q;
POS cur = {x,y};
q.push(cur);
room.vis[cur.x][cur.y]=true;
POS next;
const POS moves[] = {{0,-1}, {1,0}, {0,1}, {-1,0}};
while (false==q.empty()) {
cur = q.front();
q.pop();
for (int i=0; i<4; i++) {
next.x = cur.x+moves[i].x;
next.y = cur.y+moves[i].y;
if (next.x>=0&&next.x<room.n
&&next.y>=0&&next.y<room.m
&&'.'==room.data[next.x][next.y]
&&false==room.vis[next.x][next.y]) {
room.vis[next.x][next.y]=true;
q.push(next);
}
}
}
}
int main() {
ROOM room = {};
cin>>room.n>>room.m;
for (int i=0; i<room.n; i++) {
for (int j=0; j<room.m; j++) {
cin>>room.data[i][j];
}
}
int ans=0;
for (int i=0; i<room.n; i++) {
for (int j=0; j<room.m; j++) {
if ('.'==room.data[i][j] && false==room.vis[i][j]) {
//房间
bfs(room, i, j);
ans++;
}
}
}
cout<<ans<<endl;
return 0;
}
剪枝优化算法
就是在暴力搜索的基础上,对代码进行优化。我们可以看到最核心代码是 n*m 这个暴力搜索。如果我们将所有的房间保存起来,然后搜索范围放在保存的队列里。这样的方法不是降低算法时间复杂度,只是降低搜索的次数,剪枝技巧罢了。
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int MAXN = 2e3+4;
const int MAXM = 2e3+4;
typedef struct _POS {
int x;
int y;
} POS;
typedef struct _ROOM {
int n;
int m;
char data[MAXN][MAXM];
bool vis[MAXN][MAXM];
} ROOM;
vector<POS> myvect;
void bfs(ROOM &room, const POS &pos) {
queue<POS> q;
q.push(pos);
room.vis[pos.x][pos.y]=true;
const POS moves[] = {{0,-1}, {1,0}, {0,1}, {-1,0}};
POS cur;
POS next;
while (false==q.empty()) {
cur = q.front();
q.pop();
for (int i=0; i<4; i++) {
next.x = cur.x+moves[i].x;
next.y = cur.y+moves[i].y;
if (next.x>=0&&next.x<room.n
&&next.y>=0&&next.y<room.m
&&'.'==room.data[next.x][next.y]
&&false==room.vis[next.x][next.y]) {
room.vis[next.x][next.y]=true;
q.push(next);
}
}
}
}
int main() {
ROOM room = {};
cin>>room.n>>room.m;
char data;
for (int i=0; i<room.n; i++) {
for (int j=0; j<room.m; j++) {
cin>>room.data[i][j];
if ('.'==room.data[i][j]) {
POS pos = {i,j};
myvect.push_back(pos);
}
}
}
int ans=0;
vector<POS>::iterator it;
for (it=myvect.begin(); it<myvect.end(); it++) {
POS pos = *it;
if (false==room.vis[pos.x][pos.y]) {
bfs(room, pos);
ans++;
}
}
cout<<ans<<endl;
return 0;
}