递归地生成非重叠的计划

时间:2017-07-19 21:10:19

标签: ruby

我正在处理一些careercup.com问题,并且我试图在Ruby中递归地实现它时难以理解this one。基本上,目标是在给定一组长时间电影及其放映时间的情况下生成不重叠的时间表。

def recursive_scheduler(movies, schedule = {})
  movie, showtimes = movies.first

  showtimes.each do |showtime|
    if !schedule.has_key?(showtime)
      schedule[showtime] = movie
      if movies.length > 1
        if recursive_scheduler((movies.reject { |m| m==movie }), schedule)
          return true
        end
      else
        puts "found schedule: #{schedule}"
        return true
      end
    end
  end
  return false
end

movies = { "The Shining" => [14, 15, 16],
           "Kill Bill"  => [14, 15],
           "Pulp Fiction" => [14, 15] }

recursive_scheduler(movies)

2 个答案:

答案 0 :(得分:2)

此问题是assignment problem,这是transportation problem的特例,而linear programming problem则是https://developer.apple.com/download/的特殊类型。

变量的形式为x ij ,如果将电影1分配给时间段i并等于j,则等于0除此以外。有两组约束,一组确保每部电影分配到一个时隙,另一组最多允许一部电影分配到每个时隙。目标函数(最大化或最小化)是任意的(例如,所有变量系数都设置为零),因为我们正在寻找任何可行的解决方案。

因此,问题可以通过通用LP代码(例如,实现 Simplex 算法的代码)或使用专用算法来解决分配或运输问题。 (有关详细信息,请参阅链接。)无论选择哪种算法,如果存在,都会生成可行的计划。

答案 1 :(得分:0)

我不会解决所有问题,但会给你一些提示。

假设:

movies = { "Shining" => [14, 15, 16], 
     "kill bill" => [14, 15], 
     "Pulp fiction" => [14, 15] }

您可以使用一系列电影将该哈希值反转为每次哈希:

> times=movies.each_with_object(Hash.new { |h,k| h[k]=[] }) {|(k,v), h| 
                  v.map {|t| h[t] << k}
                  }.sort_by {|k, v| k}.to_h
=> {14=>["Shining", "kill bill", "Pulp fiction"], 15=>["Shining", "kill bill", "Pulp fiction"], 16=>["Shining"]}

然后你可以获取cartesian product值数组并保持唯一身份以推断出订单的内容:

> schedules=times.values[0].product(*times.values[1..-1])
                  .select {|arr| arr.uniq.length == arr.length}
=> [["kill bill", "Pulp fiction", "Shining"], ["Pulp fiction", "kill bill", "Shining"]]

(提示:采用笛卡尔积可以递归表示 - 我只是使用Ruby的内置方法作为快捷方式)

所以你的结果将是这两个时间表中的一个。

最后:

> times.keys.zip(schedules.transpose).map {|t,m| [t, m.uniq.join(' or ')]}.to_h
{14=>"kill bill or Pulp fiction", 15=>"Pulp fiction or kill bill", 16=>"Shining"}
祝你好运!