Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何正确布置网格_Ruby_Algorithm - Fatal编程技术网

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个值是可以的

如果暴力解决方案太慢,您仍然可以尝试启发式或近似算法

编辑:您的示例砖看起来非常人造。您的砖块尺寸是否符合某些标准,还是完全随意?也许你可以利用砖块大小的限制,如果有的话