35. 图像物体的边界

135 阅读2分钟

题目描述

给定一个二维数组M行N列,二维数组里的数字代表图片的像素,为了简化问题,仅包含像素1和5两种像素,每种像素代表一个物体2个物体相邻的格子为边界,求像素1代表的物体的边界个数。

像素1代表的物体的边界指与像素5相邻的像素1的格子,边界相邻的属于同一个边界,相邻需要考虑8个方向(上,下,左,右,左上,左下,右上,右下)。

其他约束:地图规格约束为:

  • 0<M<100
  • 0<N<100

alt

输入描述

第一行,行数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;
}