这个问题(您需要从建筑物中扔出多少只猫才能确定这种猫可以生存的最大楼层。实际上相当残酷)对于O(n ^ 3)的复杂度已经得到了公认的答案。该问题等效于此Google Code Jam,对于N = 2000000000而言应该可以解决。
似乎O(n ^ 3)解决方案不足以解决它。从解决方案页面中查找,jdmetz的解决方案(#2)似乎是O(n log n)。我不太了解该算法。有人可以解释吗?
编辑
最高的解决方案实际上是O(D*B)(使用问题的术语),但是作者注意到,对于大多数人来说D,B答案将大于2^32并且-1可以返回。 所以,他介绍maxn等于1100 -最大D和F为它是有道理的计数。 因为D, B = 10000他马上返回-1。对于D, B = 100递归公式,使用下面的公式。仅对某些“角值”(例如D = 10000, B = 2)使用直接公式。(有关“直接公式”的详细信息,请参阅他的评论)
O(D*B)
D
B
2^32
-1
maxn
F
D, B = 10000
D, B = 100
D = 10000, B = 2
为此D, B < maxn,作者在评论中提供了公式:f(d,b) = f(d-1,b)+f(d-1,b-1)+1。f这里的函数返回最多可以使用“ d尝试”和“ b鸡蛋”来确定“断点”的楼层数。 公式本身应该是不言而喻的:无论我们在哪个楼层投出第一枚鸡蛋,都有两个结果。它可能会破裂,然后我们可以检查f(d-1, b-1)下面的楼层。或者它可以“生存”,那么我们可以检查f(d-1, b)上面的楼层。以当前楼层为单位,这使其f(d-1,b)+f(d-1,b-1)+1总数为零。
D, B < maxn
f(d,b) = f(d-1,b)+f(d-1,b-1)+1
f
d
b
f(d-1, b-1)
f(d-1, b)
f(d-1,b)+f(d-1,b-1)+1
现在,可以轻松地将其编码为DP(动态编程)。如果您留下无穷大(2^32)签出,它将变得非常干净。
for (int i = 1; i < maxn; ++i) { for (int j = 1; j < maxn; ++j) { f[i][j] = f[i - 1][j - 1] + f[i - 1][j] + 1; } }
当我们有f[D][B]存储这些结果的数组时,找到D'和B'是二进制搜索。(因为函数f由d和都单调增长b)
f[D][B]
D'
B'
PS尽管我在回答“猫”问题时确实说过,有一个更快的解决方案,但实际上比我想的要 酷 :)多亏了您和 sclo (作者)!