我正在编写一个C ++程序,在较大的图像上放置一些较小的图像,使图像之间没有间隙。
例如:
给定大小为2x2(代码0),4x4(代码1),5x5(代码2)的图像
将它们放在尺寸为4x6的较大图像上
一种可能的解决方案可能是:
0a 0a 1a 1a 1a 1a
0a 0a 1a 1a 1a 1a
0b 0b 1a 1a 1a 1a
0b 0b 1a 1a 1a 1a
另一个可能是所有2x2图像或4x4图像放置在其他地方,2x2图像覆盖剩余的间隙。
我能想到的最好的是:
1.选择最小尺寸的图像并用它填充图像。
在链表中保持其起始位置。(例如:0a的开头是(0,0)。
2.然后选择下一个较大的图像(此处为4x4),制作一个4x4列表,尝试替换一组相邻的2x2图像。从2x2列表中删除它们,并在此图像的起始点的4x4列表中输入一个条目。
3.继续这样做,直到没有间隙为止。
可以通过从较小的列表中选择随机图像来制作更大的图像来实现随机性。
我们被允许使用任意数量的图像副本(0a,0b表示图像0的2个副本),但是想要使用大多数较小的图像来适合较大的图像。
是否有预先存在的算法来解决这个放置问题,这些算法易于实现并解决了保证无间隙和完全随机性的问题?
答案 0 :(得分:1)
蛮力方法很容易实现。从一些任意角落(比如左上角)开始,然后尝试将每个可用的形状放在该位置:如果它适合,找到下一个尚未覆盖的位置并迭代可用的形状等等。这可以很容易递归。
为了说明这种方法如何处理2x2(代码0),4x4(代码1),5x5(代码2)到4x6的示例情况,您可以将递归看作是探索具有左分支放置2x2的三叉树下一个空位置(X)的代码0框,中间分支放置4x4代码1,右分支放置5x5代码2。
start
/ | \
0a 0a X _ _ _ 1a 1a 1a 1a X _ finito
0a 0a _ _ _ _ 1a 1a 1a 1a _ _
_ _ _ _ _ _ 1a 1a 1a 1a _ _
_ _ _ _ _ _ 1a 1a 1a 1a _ _
/ | / | \
0a 0a 0b 0b X _ 0a 0a 1a 1a 1a 1a 1a 1a 1a 1a 0a 0a finito
0a 0a 0b 0b _ _ 0a 0a 1a 1a 1a 1a 1a 1a 1a 1a 0a 0a
_ _ _ _ _ _ X _ 1a 1a 1a 1a 1a 1a 1a 1a X _
_ _ _ _ _ _ _ _ 1a 1a 1a 1a 1a 1a 1a 1a _ _
/ | \ / | \ / | \
/ finito / finito / finito
/ / /
0a 0a 0b 0b 0c 0c 0a 0a 1a 1a 1a 1a 1a 1a 1a 1a 0a 0a
0a 0a 0b 0b 0c 0c 0a 0a 1a 1a 1a 1a 1a 1a 1a 1a 0a 0a
X _ _ _ _ _ 0b 0b 1a 1a 1a 1a 1a 1a 1a 1a 0b 0b
_ _ _ _ _ _ 0b 0b 1a 1a 1a 1a 1a 1a 1a 1a 0b 0b
/
etc
如果你想提高速度,你可以:
修剪在递归过程中传递的“代码”,因此不考虑明显太大而无法容纳在剩余空间中的区域。过滤宽度和高度都是理想的,但即使过滤对角线长度也很有用。
保存共同形成矩形区域的区域的排列,以便您可以想到覆盖10x10的排列,然后如果求解30x20,则无需从头开始重现涉及10x10解决方案的排列的解决方案。扩展这一点,您可以将解决方案报告为树。
避免/最大限度地减少从现有解决方案的镜像映像中重新生成的解决方案,例如:通过让“代码”最外面的循环在中途停止。
答案 1 :(得分:1)
你要做的第一件事就是检查 为此,您应该检查较小图像的总面积,看它是否小于或等于大图像区域。如果问题是可以解决的,您应该按大小(降序,最大的第一个)对图像进行排序,并使用强力。请记住排序部分 - 它会减少您需要提取的数量。