在网格上查找和填充封闭形状的算法

时间:2017-01-19 16:30:37

标签: algorithm search grid shape flood-fill

所以说我们有一个0的空格:

0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

你可以在上面画出形状。 1代表填充的细胞。

1 1 1 1 0 0 0 0
1 0 0 1 0 0 0 0
1 0 0 1 0 0 0 0
1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0
0 1 1 0 0 1 1 1
1 0 0 1 0 1 0 0
0 1 1 0 0 1 0 0

如果四向泛洪填充算法不会泄漏并填充形状外的任何单元格,则认为形状是闭合的。形状不能使用网格的边界作为其一侧。因此,如果我们用2s填充此网格中的所有闭合形状,我们将:

1 1 1 1 0 0 0 0
1 2 2 1 0 0 0 0
1 2 2 1 0 0 0 0
1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0
0 1 1 0 0 1 1 1
1 2 2 1 0 1 0 0
0 1 1 0 0 1 0 0

实现泛洪填充算法很简单,但我无法找到一种方法(以编程方式)填充网格中所有封闭的任意形状。我可以使用任何类型的算法或搜索吗?

2 个答案:

答案 0 :(得分:1)

洪水填充算法有什么问题?它简单有效,复杂度为O(N)。

首先扫描边缘的零值,并使用标记值3填充空白区域。 然后走进内心的地方。如果您发现零单元格,则从此单元格填充洪水,值为2.

(也许你正在寻找像connected-component labeling algorithm这样的东西。它旨在用唯一的标记值标记每个连接的区域)

答案 1 :(得分:1)

您可以先找到具有边界路径的零点:

在边界中取任意0个单元格,将其标记为-1,递归地为其所有相邻单元格执行此操作(邻居的邻居等等都设置为-1)。一旦没有边界单元为零,则将所有零单元转为2.这意味着它们仅被1包围。毕竟将所有-1转为0.这是O(n),其中n是网格中的单元格数。

这是一个(懒惰的)伪代码,假设我们有n_1xn_2网格:

function fill()
{
 for int i=1..n_1
 {
   recursivecolor(i,1);
   recursivecolor(i,n_2);
 }

 for int j=1..n_2
 {
   recursivecolor(1,j);
   recursivecolor(n_1,j);
 }

 for i=1..n_1
   for j=1 .. n_2
     if (a[i][j] == 0)
       a[i][j] = 2;

 for i=1..n_1
   for j=1 .. n_2
     if (a[i][j] == -1)
       a[i][j] = 0;
}


function recursivecolor(i,j)
{
   if (a[i][j]!=0) return;

   a[i][j] = -1;
   if (a[i-1][j] == 0)
   {   
      a[i-1][j] = -1;
      recursivecolor(i-1,j);
   }
   // do this for all neighbours of i,j cell
   // it also needs check for boundaries, e.g. i-1 should not be zero ...
}