如何检查网格内的点是否垂直/水平连接?(彼此相距1)

How do you check if points within a grid are connected vertically/horizontally? (1 away from each other)

本文关键字:连接 水平 是否 检查 何检查 网格 垂直      更新时间:2023-10-16

让我们只用 1 因为有一个点,如果没有,则用 0

例如,网格:

0 0

0 0 0

1 1 1

1 1

0 0

0 0 0

1 1 1

1 1

不会连接在一起,而

0 0

1 0 0

0

1 1 0 0

0 0 1

1 0

0 0

0 1 1

是。

我觉得使用像BFS这样的东西对于可能应该相当简单的东西来说效率非常低;还有其他选择吗?

此类问题的最佳渐近复杂度来自使用秩和路径压缩的联合查找算法。

Union find 将每个新点与组名称相关联,该组名称是唯一的、取自左侧或顶部邻居的,或者统一组(通过从一个组链接到另一个组)。

最后,所有初始唯一组的所有父组都指向同一项目,在这种情况下,集合是连接的。

进一步阅读 c++ 源代码

图像处理的进一步阅读

#include "catch.hpp"
#include <vector>
template <typename T>
T parent(std::vector<T> &links, T item)
{
    if (item == 0)
        return item;
    while (links[(size_t)item - 1] != item)
        item = links[(size_t)item - 1];
    // Should implement path compression
    return item;
}
template <typename T, int N, int M>
bool is_connected(T(&array)[N][M])
{
    // Assumption is that the type T is large enough to hold N*M/2 distinct entries
    // Thus we can use/modify the array itself to record (roots) of distinct labels
    // Of course we could copy the array into a vector of type size_t
    std::vector<T> parents;
    for (auto j = 0; j < N; j++)
    {
        for (auto i = 0; i < M; i++)
        {
            T &current = array[j][i];
            if (!current)
                continue;
            T left = i ? parent(parents, array[j][i - 1]) : 0;
            T above = j ? parent(parents, array[j - 1][i]) : 0;
            if (left == 0)
            {
                if (above)
                    current = above;
                else
                    parents.emplace_back(current = (T)(parents.size() + 1));
            }
            else
            {
                // Todo: implement rank based selection of joining the sets
                current = left;
                if (above != 0 && above != left)
                    parents[(size_t)above - 1] = left;
            }
        }
    }
    // Check that all intermediate disjoint sets have now a single root
    if (parents.size() == 0)
        return false;   // is empty set connected or not?
    auto last_item = parents.back();
    auto root = parent(parents, last_item);
    parents.pop_back();
    for (auto &group : parents)
    {
        if (root != parent(parents, group))
            return false;
    }
    return true;
}
SCENARIO("Is connected")
{
    int arr[4][4] = {
        { 1, 0, 1, 0 },
        { 1, 0, 1, 0 },
        { 1, 0, 1, 0 },
        { 1, 1, 1, 1 }
    };
    auto foo = is_connected(arr);
    CHECK(foo == true);
    arr[3][1] = 0;
    CHECK(is_connected(arr) == false);
}

BFS或DFS确实是正确的解决方案。剩下的只是利用直线网格(栅格)的属性以更有效的方式实现此类搜索算法,最好比"直接"实现更有效。例如,一些经典的 4 向光栅扫描线泛洪填充算法是在网格中搜索连接组件的好方法(请参阅"扫描线填充"部分)。