假设我有一个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的所有点,而不是外部点。我该如何修改这段代码?我应该使用其他算法吗?
答案 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,我们就让父点知道他必须是可见的,因为他是“边界”点。