题目描述
给定一个二维数组M行N列,二维数组里的数字代表图片的像素,为了简化问题,仅包含像素1和5两种像素,每种像素代表一个物体2个物体相邻的格子为边界,求像素1代表的物体的边界个数。
像素1代表的物体的边界指与像素5相邻的像素1的格子,边界相邻的属于同一个边界,相邻需要考虑8个方向(上,下,左,右,左上,左下,右上,右下)。
其他约束:地图规格约束为:
- 0<M<100
- 0<N<100
输入描述
第一行,行数M, 列数N
第二行开始,是M行N列的像素的二维数组,仅包含像素1和5
输出描述
像素1代表的物体的边界个数。如果没有边界输出0(比如只存在像素1,或者只存在像素5)。
示例1
输入:
6 6
1 1 1 1 1 1
1 5 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 5
输出:
2
示例2
输入:
6 6
1 1 1 1 1 1
1 5 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 5 1
1 1 1 1 1 1
输出:
1
思路
- 首先把5周围的1都变成0;
- 遍历0
- 遇到了0,则利用队列(bsf)将跟此0能连起来的一溜0都变成1
- 能遇到几次0就代表有几个合格的5
#include <iostream>
#include <vector>
#include <deque>
using namespace std;
int m, n;
vector<vector<int>>matrix;
// 上、下、左、右、左上、左下、右上、右下的横坐标、纵坐标偏移量
int offsets[8][2] = { {-1, 0},
{1, 0},
{0, -1},
{0, 1},
{-1, -1},
{-1, 1},
{1, -1},
{1, 1} };
// 把所有0的周围元素变为1, 如果相连,则继续,直到周围元素全部为1
// 如果两个图像边界有连接,则第二个图像周围的0也会变成1,且下次不会count++
void bfs(int i, int j)
{
deque<int>queue;
queue.push_back(i * n + j); // 将i,j存储在一个变量中,方便后续使用
matrix[i][j] = 1;
while (!queue.empty())
{
int pos = queue.front();
queue.pop_front();
int row = pos / n;
int col = pos % n;
for (const auto& offset : offsets)
{
int newRow = row + offset[0];
int newCol = col + offset[1];
if (newRow >= 0 && newRow < m && newCol >= 0 && newCol < n && matrix[newRow][newCol] == 0)
{
matrix[newRow][newCol] = 1;
queue.push_back(newRow * n + newCol);
}
}
}
}
int solution()
{
// 将5的周围所有元素变为0
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (matrix[i][j] != 5) continue;
for (const auto& offset : offsets)
{
int newI = i + offset[0];
int newJ = j + offset[1];
if (newI >= 0 && newI < m && newJ >= 0 && newJ < n && matrix[newI][newJ] == 1)
{
matrix[newI][newJ] = 0;
}
}
}
}
int count = 0;
// 遍历看能找到几个0;直到所有0都被遍历完为止
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (matrix[i][j] == 0)
{
count++;
bfs(i, j); // 将和此0有关系的0全部变为1
}
}
}
return count;
}
int main()
{
cin >> m >> n;
matrix = vector<vector<int>>(m, vector<int>(n, 0));
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
cin >> matrix[i][j];
cout << solution()<<endl;
return 0;
}