如何使用BFS算法只保留外部点

How to use the BFS algorithm to keep only the outer points?

本文关键字:保留 外部 算法 何使用 BFS      更新时间:2023-10-16

假设我有一个 500x500 的 2D 网格(从 -250 到 250)。

网格的每个单元格都有一个特定的值,从 0 到 100。

我一直在尝试做的是从点 (0, 0) 开始保留值小于 50 的所有单元格的列表,但我不想保留所有点,而只保留外部点(周长、边界、值小于 50 的单元格没有 4 个相邻单元格的值小于 50)。

实现算法的方式,我保留了所有点的列表。我应该如何修改它?如果可能的话,我想优化代码(我可以有更大的网格),所以我不想再次迭代。

pointList pointsWithValueBelow50; // The list of points with a value below 50
map<point, bool> pointDiscovered; // A map of the points we already passed through
point a = {0,0};
point b;
int value;
Queue q;
q.enqueue(a);
pointDiscovered[a] = true;
while(!q.isEmpty())
{
    a = q.dequeue(a)
    value = calculateValue(a); // Random method that verify if the points has a value below 50 in the grid
    if (value < 50)
    {
         pointsWithValueBelow50.add(a);
         b[0] = a[0]+1;
         b[1] = a[1];
         if(pointDiscovered[b] == false)
         {
             q.enqueue(b)
             pointDiscovered[b] = true;
         }
         b[0] = a[0]-1;
         b[1] = a[1];
         if(pointDiscovered[b] == false)
         {
             q.enqueue(b)
             pointDiscovered[b] = true;
         }
         b[0] = a[0];
         b[1] = a[1]+1;
         if(pointDiscovered[b] == false)
         {
             q.enqueue(b)
             pointDiscovered[b] = true;
         }
         b[0] = a[0];
         b[1] = a[1]-1;
         if(pointDiscovered[b] == false)
         {
             q.enqueue(b)
             pointDiscovered[b] = true;
         }
    }     
}

如您所见,我将值低于 50 的所有点保留在我的列表中,而不是外部点。如何修改此代码?我应该使用其他算法吗?

让我们将单元格数组视为灰度图像(其中单元格值是像素强度)。您尝试执行的操作("查找边框")是图形中的常见问题,并且有一种众所周知的算法(行进方块)来查找列表等边框(具有列表的附加属性被排序,因此当您遍历列表时,您将绕过包含感兴趣区域的多边形的顶点。

行进方块是 O(单元格)(在最坏的情况下,它只需要查看每个单元格邻域一次),并且可以并行化以获得更高的性能。根据被视为相关过渡的内容以及您是只想查找一个边界还是所有边界,有许多变化。

那里有很多实现。我读过的最干净的一个是这里(LGPL;返回所有边界;可配置的阈值) - 将其从Java转换为C++应该相对简单。

抱歉,我忘了添加我的解决方案。不幸的是,我认为它内存很重,所以任何新的答案都会被欣然接受!

pointList pointsWithValueBelow50; // The list of points with a value below 50
pointList pointsBorder;
map<point, bool> pointDiscovered; // A map of the points we already passed through
map<point, bool> pointVisible; // The final visible points
map<point, point> pointParent; // A map of the parent point
point a = {0,0};
point b;
int value;
Queue q;
q.enqueue(a);
pointDiscovered[a] = true;
while(!q.isEmpty())
{
    a = q.dequeue(a)
    value = calculateValue(a); // Random method that verify if the points has a value below 50 in the grid
    if (value < 50)
    {
         pointsWithValueBelow50.add(a);
         b[0] = a[0]+1;
         b[1] = a[1];
         if(pointDiscovered[b] == false)
         {
             q.enqueue(b)
             pointParent[b] = a
             pointDiscovered[b] = true;
         }
         b[0] = a[0]-1;
         b[1] = a[1];
         if(pointDiscovered[b] == false)
         {
             q.enqueue(b)
             pointParent[b] = a
             pointDiscovered[b] = true;
         }
         b[0] = a[0];
         b[1] = a[1]+1;
         if(pointDiscovered[b] == false)
         {
             q.enqueue(b)
             pointParent[b] = a
             pointDiscovered[b] = true;
         }
         b[0] = a[0];
         b[1] = a[1]-1;
         if(pointDiscovered[b] == false)
         {
             q.enqueue(b)
             pointParent[b] = a
             pointDiscovered[b] = true;
         }
    }
    else     
    {
        if(pointVisible[pointParent[a]] == false)
        {
            pointVisible[pointParent[a]] = true;
            pointsBorder.add(poinParent[a]);
        }
    }
}

这个想法很简单,如果我在一个值高于 50 的点,我们让父点知道他必须是可见的,因为他是"边界"点。