复制书籍UVa在线评判动态编程解决方案

时间:2014-05-15 13:48:31

标签: algorithm dynamic-programming

我可以使用二进制搜索方法解决Copying Books Problem,因为它很容易实现。但我刚开始解决动态编程问题,我想知道问题的动态编程解决方案

  

在书籍印刷发明之前,制作一本书很难   一本书的副本。所有的内容都必须手工重写   叫做抄写员。经过几次抄写员被给了一本书   几个月他完成了副本。其中一位最着名的抄写员住在这里   15世纪,他的名字是Xaverius Endricus Remius Ontius   Xendrianus(Xerox)。无论如何,这项工作非常烦人和无聊。和   加快速度的唯一方法就是雇用更多的抄写员。

     

曾几何时,有一个想要演奏的剧院合奏   着名的古董悲剧。这些戏剧的剧本分为   当然,许多书籍和演员需要更多的副本。所以他们   雇了很多抄写员来复制这些书。想象一下,你有m   书籍(编号1,2,......,m)可能有不同的数量   页面(p_1,p_2,...,p_m),你想要制作一份   他们你的任务是将这些书分成k个文字,k< =   米每本书只能分配给一个划线员,每一本书   划线员必须获得连续的书籍序列。那意味着,那里   存在越来越多的数字0 = b_0< b_1< b_2,......   < b_ {k-1}< = b_k = m $,以便我的抄写员得到一系列书籍   bi-1 + 1和bi之间的数字。制作副本所需的时间   所有的书都是由被分配最多的抄写员决定的   工作。因此,我们的目标是最小化最大页数   分配给一个划线员。你的任务是找到最佳的   分配

对于二进制搜索,我正在执行以下操作。

 Low =1 and High = Sum of pages of all books

 Run Binary search

 For Mid(Max pages assigned to a scribe), assign books greedily such that no scribe gets page more than MAX

 If scribes remain without work it means actual value is less than MID, if Books remain actual pages is more MID and I am updating accordingly.

1 个答案:

答案 0 :(得分:0)

这是一个用python编写的动态编程解决方案。我使用从0开始的索引。

k = 2  # number of scribes
# number of pages per book. 11 pages for first book, 1 for second, etc.
pages = [11, 1, 1, 10, 1, 1, 3, 3]
m = len(pages)  # number of books


def find_score(assignment):
    max_pages = -1
    for scribe in assignment:
        max_pages = max(max_pages, sum([pages[book] for book in scribe]))
    return max_pages


def find_assignment(assignment, scribe, book):
    if book == m:
        return find_score(assignment), assignment
    assign_current = [x[:] for x in assignment]  # deep copy
    assign_current[scribe].append(book)
    current = find_assignment(assign_current, scribe, book + 1)
    if scribe == k - 1:
        return current
    assign_next = [x[:] for x in assignment]  # deep copy
    assign_next[scribe + 1].append(book)
    next = find_assignment(assign_next, scribe + 1, book + 1)
    return min(current, next)


initial_assignment = [[] for x in range(k)]
print find_assignment(initial_assignment, 0, 0)

函数find_assignment将赋值作为列表返回,其中第i个元素是分配给第i个抄写员的书籍索引列表。还会返回作业的分数(抄写员在作业中必须复制的最大页数)。

动态编程的关键是首先确定子问题。在这种情况下,书籍是有序的,只能按顺序分配。因此,子问题是使用s scribes(其中n