油田——UVa 572
输入一个m行n列的字符矩阵,统计字符“@”组成多少个八连块。如果两个字符“@”所在的格子相邻(横、竖或者对角线方向),就说它们属于同一个八连块。例如,下面的示例中有两个八连块。
****@
*@@*@
*@**@
@@@*@
@@**@
说的挺不好理解的,其实就是找图中有几个连通分量,这图里右两个。
思路
这题简单,我直接广度优先了。其实学了Abbott的复仇——UVa 816,这代码可以写的更精简,但是我懒得改了。
#include "iostream"
#include "cstdio"
#include "set"
#include "vector"
#include "string"
#include "queue"
#include "sstream"
#define MAX 100
/*
Sample Input
1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0
Sample Output
0
1
2
2
*/
using namespace std;
int m,n;
int deposits[MAX][MAX];
bool safe_assert(int i, int j) {
return i >= 0 && i < m&& j >= 0 && j < n&& deposits[i][j] == 1;
}
void bfs(int i, int j) {
queue<pair<int, int>> queue;
queue.push(make_pair(i, j));
while (!queue.empty()) {
pair<int, int> kv = queue.front(); queue.pop();
i = kv.first; j = kv.second;
deposits[i][j]++;
if (safe_assert(i - 1, j-1))
queue.push(make_pair(i - 1, j-1));
if (safe_assert(i - 1, j))
queue.push(make_pair(i - 1, j));
if (safe_assert(i - 1, j + 1))
queue.push(make_pair(i - 1, j + 1));
if (safe_assert(i, j - 1))
queue.push(make_pair(i, j - 1));
if (safe_assert(i, j + 1))
queue.push(make_pair(i, j + 1));
if (safe_assert(i + 1, j - 1))
queue.push(make_pair(i + 1, j - 1));
if (safe_assert(i + 1, j))
queue.push(make_pair(i + 1, j));
if (safe_assert(i + 1, j+1))
queue.push(make_pair(i + 1, j+1));
}
}
int search() {
int group = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (deposits[i][j]==1) {
bfs(i, j);
group++;
}
}
}
return group;
}
int main() {
while (scanf("%d %d", &m,&n) != EOF) {
if (m == 0 && n == 0)break;
getchar();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
char c;
scanf("%c", &c);
deposits[i][j] = c == '@' ? 1 : 0;
}
getchar();
}
printf("%d\n", search());
}
return 0;
}