我试图弄清楚如何编写算法(在C#中),当给出时:
一组通常较小的基于图块的形状。通常为2x2,但并非总是如此。有时形状为2x1或非矩形。
一个tilemap(二维数组),其中某些tile被标记为“free”,而某些tile被“保留”。免费瓷砖指定允许使用基于图块的形状的区域,保留的瓷砖不能被形状占用。
除2x2s以外的基于图块的形状示例: http://img850.imageshack.us/img850/9057/awk.png
tilemap中“可用空间”的示例: http://img641.imageshack.us/img641/8263/spaceh.png
基本上,算法应将形状放在可用空间中,偏向顶部。它提出的解决方案不一定是“完美的”,但它应该总是能够找到解决方案(如果存在的话)。另外,我真的想避免在此算法中使用任何伪随机数。我希望它总是在给定相同输入的情况下找到相同的解决方案,即使该解决方案不是最好的解决方案。
我找到了与此相关的其他主题,但所有这些都与填充矩形空间而不是任意空间有关。
编辑:哦,形状可以水平和/或垂直翻转,但不能旋转。忘了提这个。
EDIT2:让我澄清一下。我不希望空间被填充,我想确定形状应该在哪里给出有限数量的空间。它们应该默认为顶部。
答案 0 :(得分:1)
Knuth写了一篇名为“Dancing Links”的论文,例如在http://arxiv.org/pdf/cs.DS/0011047关于简化版本的回溯搜索。他用它来例如用polyonimoes平铺一架飞机。我的猜测是,这可以用来解决你的问题 - 需要付出一些代价。我怀疑如果存在一个非常通用的方法来解决你的问题,它也可以应用于Knuth,这使得它不太可能被找到。当然,你的形状比Knuth更简单,所以也许有一些方法特别适合你的问题而且效率更高。
答案 1 :(得分:0)
正如templatetypedef所怀疑的那样,通过减少平面1-in-3 SAT来解决这个问题。
除非您希望所有可能的解决方案和形状不重复,否则跳舞链接是不合适的。假设你想要一个形状可以重复的解决方案,并且实例不比你的样本大,我建议动态编程。要平铺特定空间,将其划分为三个子空间A,B,C,使得A和C非空,并且没有放置可以同时重叠A和C.尝试最小化B的大小。对于B的每个子集S(它们的所有2 | B | ),递归地尝试覆盖A联合S并且单独地,C联合(B减去S)。如果找到相同S的解决方案,则可以将它们组合。否则,没有解决方案。用蛮力处理基础箱。