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

时间:2015-06-10 17:10:01

标签: c++ algorithm path-finding breadth-first-search

假设我有一个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的所有点,而不是外部点。我该如何修改这段代码?我应该使用其他算法吗?

2 个答案:

答案 0 :(得分:1)

让我们将单元阵列视为灰度图像(其中单元格值是像素强度)。你试图做的事情(&#34;找到边界&#34;)是图形中的一个常见问题,并且有一个众所周知的算法(Marching Squares)来找到这样的边界作为列表(具有附加属性)正在排序的列表,以便当您遍历列表时,您将绕过包含有趣区域的多边形的顶点。

行进方格是O(单元格)(在最坏的情况下,它只需要查看每个单元格邻域一次),并且可以并行化以获得更高的性能。根据所谓的相关转换以及您是否只想找到一个边界或所有边界,有许多变体。

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

答案 1 :(得分:0)

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

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,我们就让父点知道他必须是可见的,因为他是“边界”点。