题意:
一个位置上有油会扩散到别的位置(上下左右,还有对角线上的4个相邻位置,一共8个位置,也就是以某个位置为中心的切比雪夫距离为1的8个点),计算”油堆”的数目.
每一次遇到一个没有标记的有油的位置,就以它为起点进行BFS,把这一次BFS可以到达的地方标记(即漏油).然后,数油堆的方法:可以从(0,0)位置开始遍历到(n,n),遇到有油的地方,如果标记了就跳过,没有标记的就进行BFS,并且数目加1.最后输出这个数目就可以了.
代码:
// 78ms, 1824K
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
struct Position {
int x, y;
Position(int x, int y) : x(x), y(y) {
}
};
// 'adjacent' means 8 directions nearby(vertically, horizantally & diagonally)
const int DIR[8][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {-1, -1}, {1, -1}, {-1, 1} };
const int MAXN(101);
char maze[MAXN][MAXN];
bool isVisited[MAXN][MAXN];
int row, col;
inline
bool isValid(const int &x, const int &y) {
return x >= 0 && y >= 0 && x < row && y < col;
}
void bfs(int start_x, int start_y) {
queue<Position> positions;
isVisited[start_x][start_y] = true;
positions.push( Position(start_x, start_y) );
while (!positions.empty()) {
Position cur = positions.front();
positions.pop();
for (int dir = 0; dir < 8; ++dir) {
int xx = cur.x + DIR[dir][0];
int yy = cur.y + DIR[dir][1];
if (isValid(xx, yy) && !isVisited[xx][yy] && maze[xx][yy] == '@') {
isVisited[xx][yy] = true;
positions.push( Position(xx, yy) );
}
}
}
}
int main() {
//freopen("in.txt", "r", stdin);
while (cin >> row >> col) {
if (0 == row && 0 == col) break;
memset(isVisited, false, sizeof isVisited);
for (int i(0); i < row; ++i) {
for (int j(0); j < col; ++j) {
cin >> maze[i][j];
}
}
int result(0);
/* 从左到右,从上到下扫描,
*如果某个(油桶)位置没有被遍历过,就从这个位置开始以BFS的方式'扩散'(标记所有可达的位置)
*如果该(油桶)位置在之前被标记了,就不用再标记了
*/
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
if (maze[i][j] == '@' && !isVisited[i][j]) {
//cout << "(" << i << ", " << j << ")" << endl;
++result;
bfs(i, j);
}
}
}
cout << result << endl;
}
return 0;
}