Ruby 如何正确布置网格
我有许多不同大小(宽度和高度)的“砖块”和一个固定大小的容器。我想在容器内尽可能紧凑地布置砖块,从顶部开始向下移动。考虑到前面的步骤,我选择了网格在任何步骤都应该是最优的标准。到目前为止,我有以下(低效的)代码不起作用:Ruby 如何正确布置网格,ruby,algorithm,Ruby,Algorithm,我有许多不同大小(宽度和高度)的“砖块”和一个固定大小的容器。我想在容器内尽可能紧凑地布置砖块,从顶部开始向下移动。考虑到前面的步骤,我选择了网格在任何步骤都应该是最优的标准。到目前为止,我有以下(低效的)代码不起作用: def fits?(x, y, w, h) !((x + w > W) || (y + h > H)) end def overlaps?(existing, modified) existing[:x] + existing[:w] > modif
def fits?(x, y, w, h)
!((x + w > W) || (y + h > H))
end
def overlaps?(existing, modified)
existing[:x] + existing[:w] > modified[:x] && existing[:y] + existing[:h] > modified[:y] && modified[:x] + modified[:w] > existing[:x] && modified[:y] + modified[:h] > modified[:y]
end
AXIS = :x
W = 800
H = 6400
sizes = [
{ w: 200 , h: 200 },
{ w: 200 , h: 200 },
{ w: 400 , h: 400 },
{ w: 200 , h: 200 },
{ w: 200 , h: 200 },
{ w: 400 , h: 400 },
{ w: 600 , h: 600 },
{ w: 200 , h: 200 },
{ w: 800 , h: 800 },
]
existing = []
sizes.each do |size|
size[:x] = 0
size[:y] = 0
existing.each do |existing|
if overlaps?(size, existing)
if fits?(x = existing[:x] + existing[:w], y = existing[:y], size[:w], size[:h])
size[:x] = x
size[:y] = y
redo
end
if fits?(x = existing[:x], y = existing[:y] + existing[:h], size[:w], size[:h])
size[:x] = x
size[:y] = y
redo
end
case AXIS
when :x then size[:x] = 0; size[:y] = existing[:y] + existing[:h]
when :y then size[:y] = 0; size[:x] = existing[:x] + existing[:w]
end
end
end
puts "#{size[:x]} , #{size[:y]} , #{size[:w]} , #{size[:h]}"
existing << size
end
def配合?(x、y、w、h)
!((x+w>w)|(y+h>h))
结束
def重叠?(现有、修改)
现有的[:x]+现有的[:w]>修改的[:x]&现有的[:y]>修改的[:y]&修改的[:x]+修改的[:w]>现有的[:x]&修改的[:y]+修改的[:h]>修改的[:y]
结束
轴=:x
W=800
H=6400
尺寸=[
{w:200,h:200},
{w:200,h:200},
{w:400,h:400},
{w:200,h:200},
{w:200,h:200},
{w:400,h:400},
{w:600,h:600},
{w:200,h:200},
{w:800,h:800},
]
现有=[]
尺寸。每种尺寸|
大小[:x]=0
大小[:y]=0
现有。每个都不存在|
如果重叠?(大小,现有)
如果适合?(x=现有[:x]+现有[:w],y=现有[:y],尺寸[:w],尺寸[:h])
大小[:x]=x
大小[:y]=y
重做
结束
如果适合?(x=现有[:x],y=现有[:y]+现有[:h],尺寸[:w],尺寸[:h])
大小[:x]=x
大小[:y]=y
重做
结束
壳轴
当:x时,则大小[:x]=0;大小[:y]=现有[:y]+现有[:h]
当:y时,则大小[:y]=0;大小[:x]=现有[:x]+现有[:w]
结束
结束
结束
放置“#{size[:x]},#{size[:y]},#{size[:w]},#{size[:h]}”
现有的您的问题是,因此没有已知的多项式解决方案
从图中可以看出,可以轻松减少:
广义子集求和问题:给定一个集合S
和一个整数k
,当且仅当存在一个与k
求和的S
子集时,返回true
缩减:给定子集和的一个实例(S,k)
-创建一个大小为(1,k)
的容器,并且S
中每个S
的元素都是(1,S)
很容易看出,当且仅当您可以完全填充容器时,原始子集和问题的解是真的,因此上述是多项式约化,该问题是NP难问题。(注:“使其尽可能紧凑”的原始问题实际上是该问题的优化问题,仍然是NP难问题)
为这个坏消息感到抱歉。
一些备选方案正在使用指数解决方案(例如),启发式或近似算法。
注意,在一维空间中,这个问题有一个问题,使用动态规划,但我不认为它可以简单地应用于二维空间(如果有的话) 正如amit所指出的,你的问题是NP难的。然而,这不应该阻止你简单地迭代所有的砖块排列,看看哪一个是最合适的。也就是说,考虑到你没有“太多”的砖块
“太多”的值主要取决于您的计算速度和可用时间,但我的猜测是,最多14个值是可以的
如果暴力解决方案太慢,您仍然可以尝试启发式或近似算法
编辑:您的示例砖看起来非常人造。您的砖块尺寸是否符合某些标准,还是完全随意?也许你可以利用砖块大小的限制,如果有的话