【问题标题】:Find minimal wire connection找到最小的电线连接
【发布时间】:2019-03-26 09:26:17
【问题描述】:

问题

a 给了你一块 a 大小的木板。电路板上有 n 个组件,它们必须连接到电路板的边缘,且电线长度尽可能短。
电线是直的,不能重叠。

找到算法,通过这些约束将组件连接到边缘。

约束是

时间:1s
空间:无限
1 1

示例:

输入: 4 3 2 1 2 3 3 3 输出: 5 向下 向上 向上


我已经尝试过的

我发现了一种递归,让我用上面提供的数据来展示这个想法。

我有一个 n 位掩码,其中第 i 个位置的 1 表示我们考虑了这个组件,而 0 没有。

当我开始递归时,我有 n 个:

111 / | \ / | \ 011 101 110 / \ / \ / \ 001 010 001 100 010 100

当我来到最低级别时,我正好有一个1。我为这个简单的问题找到了最佳解决方案(最短的方法),然后我将其用于进一步的计算。

但是,我有一个问题,这个最优解可能会导致重叠。

【问题讨论】:

  • 能解释一下输入输出格式吗? (那是什么5)。你确定总会有解决方案吗?这个递归树如何准确地告诉你解决方案?
  • 我们在第一行收到 a,即方板的大小。然后我们得到n,即成分的数量。之后我们输入板上触点的 n 行坐标。输出的含义如下: 5 - 可能的最小导线总长度 然后是第 i 个组件的导线方向。是的,可能存在这样一种情况,即没有解决方案,但可以保证输入是正确且可解决的。
  • 这个递归树代表了我的 dp 的状态。 001 表示,我忽略组件#1 和#2,并为组件#3 找到最小可能的解决方案。然后我将它遍历到顶部并查看情况,当我只有 2 个组件时,例如011 - 我忽略组件 #1 并一起查看组件 #2 和 #3 的最小可能解决方案
  • 好的!事情现在更清楚了。我仍然不明白为什么有 5 根电线而不是 3 根作为最小解决方案。
  • 一根电线可以连接多个组件吗?除了向上或向下,电线还能向左还是向右?

标签: algorithm dynamic-programming


【解决方案1】:

目前我真的找不到比branch and bound 解决这个问题的方法更好或更聪明的方法了。它在某种程度上类似于您提出的建议,但没有多余的计算。
这里简单描述为pythonic伪代码:

def BnB(grid, components):
    queue = new_priority_queue()  # classic priority queue
    empty_sol = [None for i in range(len(components))]  # we create an 'empty' solution
    queue.push((0, 0, empty_sol))  # we push an initial empty solution on the queue (a tuple total len, index, solution)
    best_length_so_far = infinite # we keep track of the best solution seen so far
    best_sol_so_far = None
    while not queue.is_empty():
        length, index, solution = queue.pop()
        if index == len(components):  # it is a feasible solution
            if best_len_so_far > length:
                best_len_so_far = length
                best_sol_so_far = solution
        elif length < best_len_so_far:
           #  check if components[index] can have its wire 'DOWN'
           if can_put_wire(grid, components, index, 'DOWN'):
               length_to_add = path_len(grid, component, index, 'DOWN')
               new_sol = copy(solution)
               new_sol[index] = 'DOWN'
               queue.push((length + length_to_add, index + 1, new_sol))
           # do the same thing for the other directions
           if can_put_wire(grid, components, index, 'UP'):
               ....
           if can_put_wire(grid, components, index, 'LEFT'):
               ....
           if can_put_wire(grid, components, index, 'RIGHT'):
               ....
return best_sol_so_far

解决方案树的探索取决于您如何设置队列的优先级。选择要考虑的组件(而不是按照上面代码中的顺序排列它们)也有助于更快地获得解决方案。 这不会是有效的(复杂的时间指数w.r.t组件的数量),但它可以找到解决方案。

另一种可能是使用ILP(整数线性规划)来解决问题。它可以很容易地用线性约束来描述,并且可以享受 LP 求解器提供的所有优化。

【讨论】:

  • 我猜分支和边界方法并不总是提供最佳解决方案。它将接近最优,但不是最优的
  • 请提供一些有教育意义的反例。
  • 好的,给定以下输入:14\n 3 1 8 3 10 2 8 它将输出:12 LEFT LEFT DOWN 但正确的输出是:11 LEFT UP UP 这会发生,因为组件遍历的顺序。它将标记解决方案,您必须在第二点上将“错误方向”设为错误,从而将第二个组件连接到最近的边缘,即左侧边缘。尽管此解决方案已经足够好,但它并不是最佳解决方案。画图就明白了
  • 我的错,我猜,这个是解决办法
  • 是的,分支定界是一种提供最佳答案的精确方法。在我看来,它只是对纯递归(或回溯)方法的改进,如果树的某些分支没有任何机会携带一个最优解叶子,则它们将被修剪。
猜你喜欢
  • 2020-04-28
  • 1970-01-01
  • 2021-11-27
  • 1970-01-01
  • 2021-11-25
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多