请为优化难题建议更好的解决方案

时间:2016-01-28 08:25:31

标签: python algorithm dynamic-programming memoization

请在下面找到问题,解决方案及其工作实施。下面的解决方案的时间复杂度为O(n!)(如果我错了,请纠正我。)

我的问题:

1)请建议一个时间复杂度更高的解决方案。鉴于它是一个优化问题,动态编程或memoization似乎是一个更好的选择。另外,请提供一个分析,证明您的解决方案的时间复杂性。谢谢!

问题:

管道公司生产固定长度的管道n。它获得了k个管道的订单,每个管道的长度在每天(0,n)之间。编写一个算法,帮助公司使用最小数量的固定长度的管道来完成订单。

解决方法1:

对于k个订单,请考虑所有排列。对于每个排列,贪婪地计算成本。以最低成本选择排列。 我们需要两种数据结构:1)顺序:使用列表2)成本:包含所有管道的列表,其中value是管道的剩余长度。 如果我们使用长度为n的单个管道,则表示成本的数据结构为[0]。

#IMPLEMENTATION OF Solution1

import itertools
n = 10

def fulfill_element_greedily(pipes_used, order):
    eligible_pipes = filter(lambda x : x - order >= 0, pipes_used)
    if len(eligible_pipes) == 0:
        new_pipe_used = n-order
    else:
        eligible_pipes.sort(reverse=True)
        new_pipe_used = eligible_pipes[-1] - order
        pipes_used.remove(eligible_pipes[-1])
    return pipes_used + [new_pipe_used]   


def cost_for_greedy_fulfill(orders):
    pipes_used = []
    for order in orders:
        pipes_used = fulfill_element_greedily(pipes_used, order)
    return len(pipes_used)

def min_cost(orders):
    if(any(map(lambda x : x > n,orders))):
        print "Orders %s" % str(orders)
        raise ValueError("Invalid orders")
    return min(map(cost_for_greedy_fulfill,itertools.permutations(orders))) if len(orders)!=0 else 0


def test():
    assert 0 == min_cost([])
    assert 1 == min_cost([1])
    assert 1 == min_cost([5])
    assert 1 == min_cost([10])
    assert 2 == min_cost([10,2])
    assert 2 == min_cost([2,9,7])
    assert 2 == min_cost([1,7,9,3])
    return "tests passed"

print test()

#IMPLEMENTATION OF Solution1 import itertools n = 10 def fulfill_element_greedily(pipes_used, order): eligible_pipes = filter(lambda x : x - order >= 0, pipes_used) if len(eligible_pipes) == 0: new_pipe_used = n-order else: eligible_pipes.sort(reverse=True) new_pipe_used = eligible_pipes[-1] - order pipes_used.remove(eligible_pipes[-1]) return pipes_used + [new_pipe_used] def cost_for_greedy_fulfill(orders): pipes_used = [] for order in orders: pipes_used = fulfill_element_greedily(pipes_used, order) return len(pipes_used) def min_cost(orders): if(any(map(lambda x : x > n,orders))): print "Orders %s" % str(orders) raise ValueError("Invalid orders") return min(map(cost_for_greedy_fulfill,itertools.permutations(orders))) if len(orders)!=0 else 0 def test(): assert 0 == min_cost([]) assert 1 == min_cost([1]) assert 1 == min_cost([5]) assert 1 == min_cost([10]) assert 2 == min_cost([10,2]) assert 2 == min_cost([2,9,7]) assert 2 == min_cost([1,7,9,3]) return "tests passed" print test()

1 个答案:

答案 0 :(得分:0)

复杂度O(k *(2 ^ k))的动态规划算法如下:

定义包含以下2个成员的状态:

struct State {
  int minPipe;      // minimum number of pipes
  int remainingLen; // remaining length of last pipe
}

当且仅当

时,我们说状态a优于状态b
(a.minPipe < b.minPipe) or (a.minPipe == b.minPipe && a.remainingLen > b.remainingLen)

问题本身可分为2 ^ k个状态:

State states[2^k]

其中states [i]表示已经产生管道x的最佳状态(最后管道的最大剩余长度的管道的最小数量),(1&lt; = x&lt; = k),其中二进制中的第x位i的表示被设定。

例如,

states[0]: inital state, no pipe produced
states[1]: optimal state with only the 1st pipe produced
states[2]: optimal state with only the 2nd pipe produced
states[3]: optimal state with the 1st and 2nd pipe produced
states[4]: optimal state with only the 3rd pipe produced
...

通过处理每个状态x的所有先前状态:

状态[x] =从所有可能的先前状态y转移的最佳状态,其中x> y并且x和y的二进制表示之间只有1位差异。

最终答案来自州[2 ^ k - 1] .minPipe;

复杂性:每个状态最多具有(k-1)个先前状态,其中有2 ^ k个状态,因此最终复杂度为O(k * 2 ^ k),小于O(k!)< / p>