Fre*_*nöw 8 algorithm optimization flood-fill
我需要通过获取其中的"元素"数量来优化网格,并尽可能地将其最小化.当我说元素时,我指的是该网格中的一个部分.这里基本上是"输入"在视觉上看起来像什么:

想到的第一个解决方案是泛洪填充算法,但是,我有一个限制:所有元素必须有4个边,因此,所有元素必须是矩形.
我的第一个有限的方法简单包括逐个元素地循环输入网格,并检查最后一个新创建的元素是否是相同的颜色,并且具有与应该创建的元素相同的alpha - 如果是,则改为创建新元素时,它只会调整最后一个元素以进一步向下延伸1个块.
这是我正在做的一个伪代码示例:
element output_array();
element last_element = null;
for (int x = 0; x < grid_width; x++) {
for (int y = 0; y < grid_height; y++) {
color current_input_color = input_grid(x, y);
if (last_element && last_element.x === x && last_element.color === current_input_color) {
last_element.span_y++;
} else {
last_element = create_element(
x, // element.x (the x coordinate of the elements top left most grid space)
y, // element.y (the y coordinate of the elements top left most grid space)
1, // element.span_x (the number of elements to span on the x axis)
1, // element.span_y (the number of elements to span on the y axis)
curent_input_color // element.color
);
output_array.append(last_element);
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果,我得到了这个(假设我输入了前一个网格):

因此,在这个特定的实例中,我将元素数量从64减少到20.
这很好,但我的"输入网格"通常不是8x8.作为输入的更真实的网格的示例在优化之前(使用我当前的方法)和之后的957导致10201个元素.
由于这种方法显然很大程度上依赖于网格本身的结构,因此这些数字可能会有很大差异.我希望至少尽可能地减少任何给定输入网格的元素.
现在我正从一个方向接近它(垂直优化它),但我也想水平优化它.这种操作的结果不一定是完美的,但这是我设想的第一个输入网格的最佳终端网格:

在这种情况下,元素的数量从20减少到只有14 - 这在我的大网格上可能非常有用.
我似乎无法想出一种方法来利用泛洪算法,这种方式允许我考虑输入网格中的每个元素空间并将所有结果元素保持矩形/ 4边.
我认为我可能会蛮力强迫它,虽然CPU利用率/速度并不是最大的问题,但我必须在数千个元素的非常大的网格上运行它,所以浪费资源试图在如此宏大的事情上暴力规模只是不现实 - 我不认为.
Gareth Rees发布了一个非常好的答案,这个问题扩展了David Eppstein在Math Overflow上引用多位作者的回答.在一个句子中,产生最优解的算法首先是在凹顶点之间切割最大非交叉线集(在多项式时间中通过二分图中的最大独立集合找到),然后贪婪地扩展这些切割以使剩余的面是矩形.
在二分图中查找MIS需要最大匹配算法.如果这是太多的工作,那么只是贪婪的步骤,其中从每个凹顶点进行垂直切割,是2近似.