我正在尝试以最有效的方式解决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吗?