什么样的算法适用?

时间:2017-07-17 21:01:30

标签: algorithm sorting sequence

TLDR:我正在有效地寻找一种算法,该算法可以为我提供所需的最少总消息量的组合,无论它们是"顺序"和/或"分层"为了得到最终结果。

=== 对于酒店想象连续12周。

对于这些周中的每一周,都存在100美元的价格。

酒店经理决定改变所有这些周的价格

enter image description here

他的系统目前只允许他发送“顺序”的“价格变动”消息,如下所示:

  1. 第1周至第2周= 120 $
  2. 第3周至第4周= 150 $
  3. 第5周至第6周= 120 $
  4. 第7周至第9周= 200 $
  5. 第10周= 120 $
  6. 第11周= 250 $
  7. 第12周= 120 $
  8. 然而,在这种情况下,他理解发送消息会更有效率 以“分层”方式,如下所示:

    1. 第1周至第12周= 120 $
    2. 第3周至第4周= 150 $
    3. 第7周至第9周= 200 $
    4. 第11周= 250 $
    5. 哪种算法允许经理总是计算出最佳的“分层”选项,这样他就可以系统地选择最有效的方式发送消息,无论涉及多少周。请记住,有些星期不一定会改变价格。

      我正在有效地寻找一种算法,该算法可以为我提供所需的最少总消息量的组合,无论它们是"顺序"和/或"分层"为了得到最终结果。那些算法存在吗?

1 个答案:

答案 0 :(得分:1)

这是一个在Python中自上而下的memoized递归,应该在O(n ^ 4)时间内解决这个问题(实际上稍微长一点,因为它也跟踪要做的移动 - 但这可以被优化掉):

class Memoize:
    def __init__(self, fn):
        self.fn = fn
        self.memo = {}
    def __call__(self, *args):
        if not self.memo.has_key(args):
            self.memo[args] = self.fn(*args)
        return self.memo[args]

@Memoize
def best_messages(a,b,value=None):
    """Return moves needed to make range old[a:b] have the target values

If value is not None, it means the range has been set to the given value
"""
    if value is None:
        while a<b and new[a]==old[a]:
            a+=1
        while a<b and new[b-1]==old[b-1]:
            b-=1     
    else:
        # Skip values that are correct
        while a<b and new[a]==value:
            a+=1
        while a<b and new[b-1]==value:
            b-=1     
    if a==b:
        return [] # Nothing to change

    best = None
    for s in range(a,b):
        for e in range(s+1,b+1):
            target = new[s]
            if target==new[e-1]:
                moves = [ (s,e,target) ] + best_messages(s,e,target) + best_messages(a,s,value) + best_messages(e,b,value) 
                if best is None or len(moves)<len(best):
                    best = moves
    return best

old = [100,100,100,100,100,100,100,100,100,100,100,100]
new = [120,120,150,150,120,120,200,200,200,120,250,120]
for s,e,value in best_messages(0,len(old))  :
    print "Week {} to Week {} = {}".format(s+1,e,value)

基本原则是只考虑我们将更新中的第一个和最后一个设置为最终目标值的更新是有意义的,否则我们可以使更新更短并且仍然采用相同数量的移动。

更新

我认为如果你改变的话,它可以在O(n ^ 3)时间内进行优化:

for s in range(a,b):

s=a