kuangbin带你飞——专题一 简单搜索(12)
题目来源:HDU 1241 Oil Deposits
HDU网址改动,VJ无法正常提交,附HDU新网址
题解
这题类似连通图问题,判断几个油井是否属于同一个油田,并且输出油田数目。
可以通过遍历所有的油井,如果该油井不属于任意一个油田(vis == 0)
,则对它进行BFS(广度优先搜索)
,寻找和他属于同一个油田的油井,并且使它们的标记vis
都为 1。
我的代码选择 C++ 编译器会Compilation Error,所以选择G++编译器
。
AC代码
#include <iostream>
#include <map>
#include <queue>
#include <cstring>
using namespace std;
const int maxn = 1e2 + 5;
#define inf 0x3f3f3f3f
// 地图数组 mp,标记数组 vis,方向数组 dx,dy
int mp[maxn][maxn];
int vis[maxn][maxn];
int dx[] = {-1, -1, -1, 0, 1, 1, 1, 0},
dy[] = {-1, 0, 1, 1, 1, 0, -1, -1};
int m, n;
void bfs(int x, int y);
// 遍历每一个油井
int solve()
{
int sum = 0;
for (int i = 1; i <= m; ++i)
for (int j = 1; j <= n; ++j)
// 当这个油井不属于已知的任意一个油田时
if (mp[i][j] && !vis[i][j])
{
// 油田数目 + 1
++sum;
// 对该油井进行广度优先搜索
bfs(i, j);
}
return sum;
}
void bfs(int x, int y)
{
// 起点入队
queue<pair<int, int>> q;
q.push(make_pair(x, y));
vis[x][y] = 1;
while (!q.empty())
{
pair<int, int> p = q.front();
q.pop();
// 遍历八个方向
for (int i = 0; i < 8; ++i)
{
if (mp[p.first + dx[i]][p.second + dy[i]] && !vis[p.first + dx[i]][p.second + dy[i]])
{
// 标记更新,新油井入队
vis[p.first + dx[i]][p.second + dy[i]] = 1;
q.push(make_pair(p.first + dx[i], p.second + dy[i]));
}
}
}
}
int main()
{
while (~scanf("%d%d", &m, &n))
{
string str;
if (!m && !n)
break;
// 初始化数组
memset(mp, 0, sizeof(mp));
memset(vis, 0, sizeof(vis));
// 控制输入
for (int i = 1; i <= m; ++i)
{
cin >> str;
for (int j = 1; j <= n; ++j)
if (str[j - 1] == '*')
mp[i][j] = 0;
else
mp[i][j] = 1;
}
printf("%d\n", solve());
}
return 0;
}