在2D阵列中找到形状,然后进行优化


11

我刚刚被允许使用一张图像...下面的游戏图像显示了一些变暗的块,这些块被认为是“ T”形的一部分。可以看出,代码使带有红色斑点的块变暗,而没有看到带有绿色轮廓的“ T”形。

找到所需的模式,但尚未优化

我的代码遍历x / y,将块标记为已使用,旋转形状,重复,更改颜色,重复。

我已经开始尝试以极大的恐惧来修复此检查。当前的想法是:

  • 遍历网格并记下所有模式出现的情况(不使用标记框),并将其放入数组中
  • 再次循环遍历网格,这次注意哪些块被哪些模式占用,因此哪些块被多个模式占用。
  • 再次遍历网格,这次注意哪些模式阻碍了哪些模式

感觉不错... 我现在该怎么办?

我必须

  • 尝试各种形状相互冲突的组合,从首先阻碍大多数其他图案的形状开始。我该如何处理?
  • 使用说我有3个相互冲突的形状占据8个块的理性,每个形状是4个块,因此我最多只能有两个形状。

(我也打算合并其他形状,在进行冲突形状处理时可能需要考虑分数加权,但这可能是另一天)

我不认为这是一个垃圾箱包装问题,但是我不确定要寻找什么。希望有道理,谢谢您的帮助

编辑尽管有明确的问题,每个人似乎都已经了解了,是的,

我想在每种颜色中找到最大的“ T”形

(因为如果我给你2分,而你又获得3分,你会有点生气)


一个贪婪的算法可能是将电路板分割成连接块的集合。然后,对于每个集合,您都可以尝试用形状填充,并根据剩余的不会变暗的块的数量给填充打分。有点让我想到了en.wikipedia.org/wiki/Knapsack_problem
乔纳森·康奈尔

2
我认为这个问题中缺少一些东西。您是否要制定一种算法,以找到尽可能多的“ T”形组?
Markus von Broady,2012年

如果我了解您,那么您将朝着正确的方向前进。您不是很清楚,如果您能详细说明的话,我会喜欢的。
AturSams 2012年

Answers:


3

让我看看是否正确,红色标记的块是蓝色,算法找到了T形并将其标记为红色,对吗?您的目标是找到尽可能多的带有相同色块的T形,我希望到目前为止是正确的。当前,一旦找到它们就将它们标记出来,这会降低算法的实用性(因为您可能会错过最佳解决方案)。您计划搜索所有形状,然后选择要使用的形状和不使用的形状。到目前为止,我是否正确?因为当算法完成时,您希望最大化包含在T形中的块数量。

如果我是正确的话,以下是我认为适合您情况的最佳解决方案。

我们将使用整数线性编程。

我相信我过去曾经使用过这个:

http://sourceforge.net/projects/lpsolve/

http://lpsolve.sourceforge.net/5.5/Java/README.html

(您可以将其与多种语言一起使用,我将其与PHP,Java和C一起使用)

我们要做的是在板上注册所有可能的T形,然后使用ILP最大化覆盖的块数量。ILP呈指数级复杂。考虑到电路板的尺寸,这将不是问题。我在使用ILP的图形上遇到了更复杂的最小/最大问题,完成它只花了不到一秒钟的时间,而数百个顶点最多花了30-90秒(在您的情况下,它落在了几分之一秒的时间内)。

我建议做的是:

  1. 查找所有可能的线形
  2. 查找相同颜色的线形之间的所有交点
  3. 找到所有可能的T形,搜索所有相交。
  4. 在线性问题中为每个T形(0 <= Bi <= 1)定义一个布尔变量,因为值是整数,所以留下0或1。
  5. 为每对相交的T形做条件(Bi + Bj <= 1
  6. 目标函数为(“ T”形(i)* Bi的块总和)
  7. 运行求解器,并在最佳解决方案中,将求解器对应布尔值的T形变暗,其中的布尔值为1。

这是宝贵的知识,我经常在工作项目中使用线性求解器。

从本质上讲,ILP是解决选择问题的一种方法,您希望为某些线性函数实现最大值或最小值。

您可以在此处了解更多信息,使用Integer线性编程和线性编程对于程序员而言是相同的,只是Integer对于计算机而言要复杂得多,这可能会导致运行时间较长。并非您的情况如此,这非常简单,最坏的情况下只需不到几毫秒的时间。

我想您可以在这里阅读更多内容:

http://en.wikipedia.org/wiki/Integer_linear_programming#Integer_unknowns

这很好地解释了这一点:

http://fisher.osu.edu/~croxton_4/tutorial/

从根本上说,这是一个决策问题解决者,如何制定决策以最大化您想要的结果。假定判断结果的函数是线性的(在您当前的特定情况下)。在这种情况下,判断结果的函数会汇总您决定变暗的所有T形的块。

在数学上,如何设置变量:在我们当前的情况下,布尔值(是否用索引i使T形状变暗)是否达到最佳值以最大化我们想要的结果:使尽可能多的块变暗而不使相交的T形状变暗。只要设置了所有变量,就可以使用线性函数计算出所需的结果,它将解决该问题。在我们的案例中,我们检查我们变暗了哪些T形,然后求和它们覆盖的块。

在此处输入图片说明

我知道这并非易事,因此,如果您选择大步向前,请随时发表评论,我会详细说明。


谢谢亚瑟的帮助。可能需要读取几次才能消化。是的,您正确理解了问题。如果您要详细说明,我会很感兴趣(不,不,这不是一件小事),但这应该可以帮助我了解我的发展方向!
汇编器

您使用哪种语言来实现?
AturSams,2012年

动作3!每个人的最爱!
组装商2012年

同样在这里。我将在as3中编写一个实现,并将其上传到github上以供下载并进行注释,并逐步进行操作-今天晚些时候可以完成它
AturSams 2012年

您是否希望在特定区域1 -7中添加更多评论或详细说明?顺便说一句,这对我们AS3爱好者来说是个好消息,Adobe发布了支持C ++的FlasCC,因此我们可以轻松使用现有的线性求解器。:)
AturSams 2012年

4

一旦列出了网格中所有(可能重叠的)T形的列表,剩下的就是最大的包装问题。

通常,这是一个NP完全问题。但是,您的网格足够小(通常分解为更小的独立子问题),因此很可能可以获取精确的解决方案。


附录:这是一个基本的回溯搜索算法,可以解决这个问题:

function max_packing_recursive ( set A, set S, set M ):
    if |M| < |S| then let M = S;
    for each shape X in A do:
        remove X from A;
        let B = A;
        remove all shapes that intersect with X from B;
        if |M| < |B| + |S| + 1 then:        // upper bound
            let M = max_packing_recursive( B, S + {X}, M );
        end if
        if |M| >= |A| + |S| then return M;  // shortcut
    end for
    return M;
end function

function max_packing( set A ):
    return max_packing_recursive( A, {}, {} );
end function

这里,{X, Y, Z}表示包含的元素的集合XYZ(与{}是空集),并且|Q|表示所述集合的大小Q

在递归函数中,集合A包含可用于其余解S的形状,包含当前解候选中的形状,并且M是迄今为止的最大解(您可能希望将其存储为全局变量,而不是将其返回到呼叫链)。重要的优化是在标记为的行上进行// upper bound,该操作会修剪搜索树的分支,这些分支可能无法返回比更好的解决方案M

(实际上,由于我们知道每个T形都恰好包含四个位点,因此,用|B|,中的形状B除以4并四舍五入的不同位点的数量代替,可以获得更好的上限|A|。标有// shortcut)的行。但是,上述算法可用于任意形状的集合。)

我上面没有实现的一种可能的其他优化方法是,在递归函数的开头检查是否A分为多个独立的子集,即不同子集中没有形状重叠的意义,如果是,则应用将算法分别应用于每个子集。(无论如何,您肯定希望调用递归算法之前在顶层至少执行一次此操作。)在对形状A进行循环之前对其进行适当排序(例如,按重叠形状的数量增加顺序)也可能会有所帮助。


是的,由于问题的大小,我认为他可以使用ILP相对轻松地解决它。.2 ^ 20〜= 1,000,000因此,由于只能有这么多的T形,为此,他应该使用线性求解器。它显然是指数复杂的(至少直到有人设法证明p = np为止)。该大小允许在这种相对简单的情况下避免启发式。
AturSams,2012年

Ilmari,非常感谢。这个答案也将需要一些去了解。任意形状的位在将来的迭代中可能很有用。
汇编器
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.