假设我们有一个边长为S的正方形,以及长度为X且宽度为Y的矩形图块的N个副本。程序必须显示这些副本可以在网格中排列的所有方式,以便没有两个副本可以互相接触。
通过显示,我的意思是它必须显示网格中每个副本左上角的坐标集。
我尝试按以下方式进行:
找到一个基本案例,我尝试将每个副本放置为1平方分隔。 例如,对于6x6网格上的1x2图块的6个副本,基本情况为
xx_xx_
______
xx_xx_
______
xx_xx_
______
将最后一个图块移动到可能的位置。
将最后一个图块返回到基本案例,将最后一个图块移动到可能的位置。重复步骤2.
为每个瓷砖做回来。
基本上问题是我找不到行数或列数差异为1但不相互接触的情况。例如,我找不到这种情况:
xx____ This tile
___xx_ and this one has a difference in row numbers 1.
xx____
___xx_
xx____
___xx_
你能说点什么吗?或者可能是更有效的算法?
注意:我尝试在Prolog中实现它。
答案 0 :(得分:3)
你会发现这个问题适合于约束编程(这与你试图使用的Prolog相差不远):
美丽的是,通过上面你声明性地指定了问题,然后你最喜欢的约束求解器(我去GECODE)去找你所有的解决方案。如果您的规格不完整,您会得到以意想不到的方式触摸或重叠的瓷砖,您可以修改规格而不必重新发明轮子。这将适用于相当大的问题实例...当你可以添加巧妙的修剪搜索树的方法时,你只需要开始发明聪明的算法,如果你需要大量的S工资。
答案 1 :(得分:0)
每次填充特定行时,可以对上一行使用位掩码。例如:
如果前一行如下:
XX----
然后有一个像110000这样的位掩码。要填充下一行,请注意你不要使用位掩码中有1的位置。
所以你可以这样做:
for(int i=0;i<(1<<S);i++)
if(i & bitmask)
{
//can't place tile in this fashion as few tiles of previous row touch this row's tiles
continue;
}
else
{
//No conflicts between rows, but with in this row there could be touching tiles as in 111100
//Use a for loop to check if the given row has no two tiles touching
//Check if each string of 1's is of length X
//If all is well recursively call this function to fill the next row using i as the bitmask
}
我会让你弄清楚实际的实施情况。