改进Codejam的“无限煎饼屋”的解决方案

时间:2019-03-09 14:00:14

标签: python python-3.x algorithm time-complexity

我正在尝试以最有效的方式解决Codejam 2015的Infinite House of Pancakes问题。我当前的解决方案类似于analysis中给出的解决方案(但使用Python而不是C ++):

def solve():
    T = int(input())  # the number of test cases

    for case in range(1, T+1):
        input()  # the number of diners with non-empty plates, ignored
        diners = [int(x) for x in input().split()]

        minutes = max(diners)  # the max stack of pancakes (= the max time)

        # try to arrange all pancakes to stacks of equal height
        for ncakes in range(1, minutes):
            s = sum([(d - 1) // ncakes for d in diners if d > ncakes])  # number of special minutes
            if s + ncakes < minutes:
                minutes = s + ncakes

        print(f'Case #{case}: {minutes}')

此解决方案的时间复杂度为O(D*M),其中D是用餐人数,M是薄煎饼的最大数量。

但是,分析中还提到了另一种解决方案O(D*sqrt(M) + M)

  

尽管上面的算法足够快   解决我们的问题,我有一个甚至更快的算法。请注意   ceil(a / 1),ceil(a / 2),...的列表最多只能更改值   2 * sqrt(a)次。例如,如果a = 10,则列表为:10、5、3、3、2、2,   2,2,2,1,1,...。该列表仅更改值4倍,该值较小   超过2 * sqrt(10)!因此,我们可以在列表更改时进行预先计算   每个进餐者的值(仅O(D * sqrt(M)))。我们可以跟踪这些   表中的值更改。例如,如果Pi = 10,我们可以有一个表   Ti:10,-5,-2、0,-1、0、0、0、0,-1、0,...。请注意,前缀   该表的总和实际上是:10、5、3、3、2、2、2 .....更多   重要的是,此表是稀疏的,即它只有O(sqrt(M))   非零。如果我们对所有Ti进行矢量加法,我们可以得到一个表   其中前缀和索引x处的每个条目都包含   ceil(Pi / x)。然后,我们可以在代码中计算ceil(Pi / x)-1的总和   上面的方法是用数字减去前缀和的第x个索引   食客。因此,仅需要另一次O(M)通过即可计算   候选答案,这给了我们O(D * sqrt(M)+ M)的运行时间。一种   解决方案快得多!

任何人都可以给我提示如何将其转换为Python吗?

0 个答案:

没有答案