把猫扔出窗外
想象一下你和一只猫在一栋高楼里。猫从低层窗户掉下来可以幸存,但如果从高楼层扔下就会死亡。你如何用最少的尝试次数算出猫能存活的最长跌落时间?
显然,如果你只有一只猫,那么你只能线性搜索。先把猫从一楼扔下去。如果它幸存下来,从第二个扔掉它。最终,猫从f层被扔出去后就会死。然后您就知道 f-1 层是最大安全楼层。
但如果你有不止一只猫怎么办?您现在可以尝试某种对数搜索。假设建筑物有 100 层,并且您有两只一模一样的猫。如果你把第一只猫扔出了50层,它死了,那么你只需要线性搜索50层。如果您第一次尝试时选择较低的楼层,您可以做得更好。假设您选择一次解决 20 层楼的问题,并且第一个致命楼层是#50。在这种情况下,您的第一只猫将从 20 层和 40 层的飞行中幸存下来,然后从 60 层死亡。您只需单独检查 41 层到 49 层即可。总共进行了 12 次尝试,这比尝试使用二元消除时需要的 50 次要好得多。
一般来说,对于拥有 2 只猫的 n 层建筑,最佳策略是什么?最坏情况的复杂性是什么?对于 n 层楼和 m 只猫呢?
假设所有猫都是等价的:它们都会从给定的窗户坠落而生存或死亡。而且,每次尝试都是独立的:如果猫从跌倒中幸存下来,它就完全没有受伤。
这不是家庭作业,尽管我可能已经解决过一次学校作业。这只是今天突然出现在我脑海中的一个异想天开的问题,但我不记得解决方案了。如果有人知道这个问题或解决算法的名称,那就加分了。
Imagine you're in a tall building with a cat. The cat can survive a fall out of a low story window, but will die if thrown from a high floor. How can you figure out the longest drop that the cat can survive, using the least number of attempts?
Obviously, if you only have one cat, then you can only search linearly. First throw the cat from the first floor. If it survives, throw it from the second. Eventually, after being thrown from floor f, the cat will die. You then know that floor f-1 was the maximal safe floor.
But what if you have more than one cat? You can now try some sort of logarithmic search. Let's say that the build has 100 floors and you have two identical cats. If you throw the first cat out of the 50th floor and it dies, then you only have to search 50 floors linearly. You can do even better if you choose a lower floor for your first attempt. Let's say that you choose to tackle the problem 20 floors at a time and that the first fatal floor is #50. In that case, your first cat will survive flights from floors 20 and 40 before dying from floor 60. You just have to check floors 41 through 49 individually. That's a total of 12 attempts, which is much better than the 50 you would need had you attempted to use binary elimination.
In general, what's the best strategy and it's worst-case complexity for an n-storied building with 2 cats? What about for n floors and m cats?
Assume that all cats are equivalent: they will all survive or die from a fall from a given window. Also, every attempt is independent: if a cat survives a fall, it is completely unharmed.
This isn't homework, although I may have solved it for school assignment once. It's just a whimsical problem that popped into my head today and I don't remember the solution. Bonus points if anyone knows the name of this problem or of the solution algorithm.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
根据Radiolab 最近的一集(关于“坠落”),一只猫到达了生命末期速度达到9楼。之后,它会放松并且不太可能受伤。有的猫从 30 层以上摔下来后完全没有受伤。最危险的楼层是 5 至 9 层。
According to a recent episode of Radiolab (about "Falling"), a cat reaches terminal velocity by the 9th floor. After that, it relaxes and is less likely to be hurt. There are completely uninjured cats after a fall from above the 30th. The riskiest floors are 5th to 9th.
对于 n 层楼和 m 只猫的一般情况,您可以轻松地编写一点 DP(动态规划)。
主要公式,
a[n][m] = min(max(a[k - 1][m - 1], a[n - k][m]) + 1) :对于 1 中的每个 k ..n
,应该是不言自明的:k - 1
层楼要检查(都在k 层以下)
)和m - 1
只猫(a[k - 1][m - 1]
)。n - k
层楼(k
以上的所有楼层),并且仍然有m
只猫。max
。+ 1
来自我们刚刚进行了一次尝试的事实(无论猫是否幸存)。min(f(k)) : for k in 1..n
。它与 Gaurav Saxena 的 (100, 2) 链接的 Google 结果一致。
如果您将最佳
k
保存在另一个数组中,您可以轻松找到策略(如何扔第一只猫)。还有一个更快的解决方案,不涉及 O(n^3) 计算,但我已经有点困了。
编辑
哦,是的,我记得以前在哪里看到过这个问题。
You can easily write a little DP (dynamic programming) for the general case of n floors and m cats.
The main formula,
a[n][m] = min(max(a[k - 1][m - 1], a[n - k][m]) + 1) : for each k in 1..n
, should be self-explanatory:k - 1
floors to check (all belowk
) andm - 1
cats (a[k - 1][m - 1]
).n - k
floors left (all floors abovek
) and stillm
cats.max
.+ 1
comes from the fact that we've just used one attempt (regardless of whether cat has survived or not).min(f(k)) : for k in 1..n
.It agrees with Google result from Gaurav Saxena's link for (100, 2).
You can easily find strategy (how to throw first cat), if you save best
k
in another array.There's also a faster solution, not involving O(n^3) computations, but I'm a bit sleepy already.
edit
Oh yeah, I remember where I saw this problem before.
解决这个问题的最佳策略是首先利用物理定律调查你的假设成立的概率。
如果你这样做了,你会发现离地面的距离越远,猫的生存机会实际上就越大。当然,假设您从更高的建筑物(例如双子塔)扔它,而不是从更高的山(例如珠穆朗玛峰)扔它。
编辑:
实际上,您会看到未完成的骆驼分布。
首先,猫死亡的概率很低(海拔非常低),然后它会变得更高(低海拔),然后再次降低(更高海拔),然后再次变得更高(海拔非常高)。
猫死亡概率与离地高度函数关系的图表如下所示:
(3点完成,因为骆驼分发未完成)
更新:
猫的最终速度为 100 公里/小时(60 英里/小时)[=27.7m/s = 25.4 码/秒]。
人类终端速度为 210 km/h (130mph)。[=75m/s = 68.58 码/s]
终端速度来源:
http://en.wikipedia.org/wiki/Cat_righting_reflex
学分:
谷歌
我需要稍后验证:
http://en.wikipedia.org/wiki/Terminal_velocity
http://www.grc.nasa.gov/WWW/K -12/airplane/termv.html
The best strategy for solving this problem is investigating, using the law of physics, the probability of your assumptions being true in the first place.
If you would have done so, you'd realize that the cat's chances of survival actually increase the higher the distance to ground is. Of course, assuming you throw it from an ever higher building, such as the petronas towers, and not an ever higher mountain, such as the mount everest.
Edit:
Actually, you'd see an unfinished camel distribution.
First, the probability of the cat dying is low (very low altitude), then it gets higher (low altitude), then again lower (higher altitude), and then again higher (very high altitude).
The graph for the probability of cat dying as a function of altitude above ground looks like this:
(finish at 3, because unfinished camel distribution)
Update:
A cat's terminal velocity is 100 km/h (60mph) [=27.7m/s = 25.4 yards/s].
Human terminal velocity is 210 km/h (130mph).[=75m/s = 68.58 yards/s]
Terminal velocity source:
http://en.wikipedia.org/wiki/Cat_righting_reflex
Credits:
Goooooogle
I need to verify later:
http://en.wikipedia.org/wiki/Terminal_velocity
http://www.grc.nasa.gov/WWW/K-12/airplane/termv.html
我第一次在 Steven Skiena 的算法设计手册(练习 8.15)中读到这个问题。它遵循关于动态规划的一章,但是您不需要了解动态规划来证明策略的精确界限。首先是问题陈述,然后是下面的解决方案。
只有 1 个鸡蛋
从第一层开始从每个楼层扔鸡蛋将在(最坏的)n 次操作中找到关键楼层。
没有更快的算法。在任何算法中的任何时间,让 g 是已知鸡蛋不会破裂的最高楼层。该算法必须在任何更高楼层 h > 之前测试楼层 g+1。 g+1,否则如果鸡蛋从h层破裂,它无法区分f=g+1和f=h。
2 个鸡蛋
首先,我们考虑 k=2 个鸡蛋的情况,此时 n = r**2 是完全平方数。这是一个需要 O(sqrt(n)) 时间的策略。首先以 r 层的增量掉落第一个鸡蛋。当第一个鸡蛋破裂时,比如在
ar
楼层,我们知道临界楼层 f 必须是(a-1)r
(a-1)r
(a-1)r
(a-1)r
(a-1)r
(a-1)r
(a-1)r
(a-1)r f <= ar
。然后,我们从(a-1)r
开始,从每一层扔下第二个鸡蛋。当第二个鸡蛋破裂时,我们就找到了临界层。我们最多在 r 次中掉落每个鸡蛋,因此该算法在最坏情况下需要 2r 次操作,即 θ(sqrt(n))。当n不是完全平方数时,取r = ceil(sqrt(n)) ∈ θ(sqrt(n))。该算法仍然是 θ(sqrt(n))。
证明任何算法至少需要 sqrt(n) 时间。假设有一个更快的算法。考虑它掉落第一个鸡蛋的楼层顺序(只要它不破裂)。由于它下降的次数少于 sqrt(n),因此必须有至少 n/sqrt(n) 的间隔,即 sqrt(n)。当 f 处于该区间时,算法将必须使用第二个鸡蛋来调查它,并且必须逐层调用 1 个鸡蛋的情况来完成此操作。矛盾。
k 个鸡蛋
针对 2 个鸡蛋提出的算法可以轻松扩展到 k 个鸡蛋。以恒定的间隔掉落每个鸡蛋,该间隔应视为 n 的 k 次方。例如,对于n=1000且k=3,第一个鸡蛋的搜索间隔为100层,第二个鸡蛋的搜索间隔为10层,最后一个鸡蛋的搜索间隔为1层。
类似地,我们可以通过 k=2 证明归纳来证明没有更快的算法
θ(n**(1/k))
。精确解
我们通过优化第一个鸡蛋的掉落位置(g 层)来推导递归,假设我们知道较小参数的最优解。如果鸡蛋破裂,我们可以用 k-1 鸡蛋探索下面的 g-1 层。如果蛋幸存下来,我们在上面有 ng 层楼可以用 k 个蛋进行探索。魔鬼为我们选择了最坏的。因此,对于 k>1,递归
I first read this problem in Steven Skiena's Algorithm Design Manual (exercise 8.15). It followed a chapter on dynamic programming, but you don't need to know dynamic programming to prove precise bounds on the strategy. First the problem statement, then the solution below.
Only 1 egg
Dropping the egg from each floor starting at the first will find the critical floor in (at-worst) n operations.
There is no faster algorithm. At any time in any algorithm, let g the highest floor from which the egg has been seen not to break. The algorithm must test floor g+1 before any higher floor h > g+1, else if the egg were to break from floor h, it could not distinguish between f=g+1 and f=h.
2 eggs
First, let's consider the k=2 eggs case, when n = r**2 is a perfect square. Here's a strategy that takes O(sqrt(n)) time. Start by dropping the first egg in increments of r floors. When the first egg breaks, say at floor
ar
, we know the critical floor f must be(a-1)r < f <= ar
. We then drop the second egg from each floor starting at(a-1)r
. When the second egg breaks, we have found the critical floor. We dropped each egg at most r time, so this algorithm takes at-worst 2r operations, which is Θ(sqrt(n)).When n isn't a perfect square, take r =
ceil(sqrt(n)) ∈ Θ(sqrt(n))
. The algorithm remains Θ(sqrt(n)).Proof that any algorithm takes at least sqrt(n) time. Suppose there is a faster algorithm. Consider the sequence of floors from which it drops the first egg (so long as it doesn't break). Since it drops fewer than sqrt(n), there must be an interval of at least n/sqrt(n) which is sqrt(n). When f is in this interval, the algorithm will have to investigate it with the second egg, and that must be done floor-by-floor recalling the 1-egg case. CONTRADICTION.
k eggs
The algorithm presented for 2 eggs can be easily extended to k eggs. Drop each egg with constant intervals, which should be taken as the powers of the kth root of n. For example, for n=1000 and k=3, search intervals of 100 floors with the first egg, 10 with the second egg, and 1 with the last egg.
Similarly, we can prove that no algorithm is faster
Θ(n**(1/k))
by inducting from the k=2 proof.Exact solution
We deduce the recurrence by optimising where to drop the first egg (floor g), presuming we know optimal solutions for smaller parameters. If the egg breaks, we have the g-1 floors below to explore with k-1 eggs. If the egg survives, we have n-g floors above to explore with k eggs. The devil chooses the worst for us. Thus for k>1 the recurrence
这不是假设您使用的是“同一只猫”吗?
你可以用数学方法来解决它,但这就是数学的好处……在正确的假设下,0 可以等于 1(对于较大的 0 值)。
从实际的角度来看,你可以得到“相似的猫”,但你不能得到“同一只猫”。
你可以尝试凭经验确定答案,但我认为会有足够的统计差异,以至于答案 。
您可以尝试使用“同一只猫”,但这行不通,因为在第一次掉落后,它不再是同一只猫(类似地,一个人永远不能两次踏入同一条河流)
或者,您可以汇总猫的健康状况,以非常接近的间隔进行采样,并找到猫“大部分活着”的高度(与“公主新娘”中的“大部分死亡”相反)。平均而言(直到最后一个间隔)
我认为我已经偏离了最初的意图,但如果你走经验路线,我投票支持从尽可能高的高度开始,并随着高度的降低而继续掉落猫,直到它们消失为止。统计上存活下来,然后对幸存的猫进行重新测试以确定。
Doesn't this assume you're using "The Same Cat"?
You can approach it mathematically, but that's the nice thing about math... with the right assumptions, 0 can equal 1 (for large values of 0).
From a practical stand-point, you can get 'Similar Cats", but you can't get "The Same Cat".
You could try to determine the answer empirically, but I would think that there would be enough statistical differences that the answer would be statistically meaningless.
You could try to USE "The Same Cat", but that wouldn't work, as, after the first drop, it's no longer the same cat. (Similarly to, onecan never step into the same river twice)
Or, you could aggregate the health of the cat, sampling at extremely close intervals, and find the heights for which the cat is "mostly alive" (opposed to "mostly dead" from "The Princess Bride"). The cats will survive, on average (up to the last interval).
I think I've strayed from the original intent, but if you're going the empirical route, I vote for starting as high as possible and continuing to drop cats as the height decreases until they statistically survive. And then re-test on surviving cats to be sure.
我采用了稍微不同的方法来产生解决方案。
我首先使用以下方法计算出使用x只猫和y个猜测可以覆盖的最大楼层。
从 1 层楼开始,不断增加猜测数量,同时跟踪检查的楼层、检查过的猜测以及每层楼还剩下多少只猫。
重复此操作最多 y 次。
这个非常低效的代码来计算给定的答案,但对于少量的猫/楼层来说仍然有用。
Python 代码:
对于 2 只猫,在 x 次猜测中可以识别的最大楼层是:
1, 3, 6, 10, 15, 21, 28...
适合 3 只猫:
1, 3, 7, 14, 25, 41, 63...
适合 4 只猫:
1, 3, 7, 15, 30, 56, 98...
经过广泛的研究(主要涉及在 OEIS) 我注意到x的最大楼层遵循分段组合图案。
适合 2 只猫:
n < 2 : 2^n - 1
n >= 2 : C(n, 1) + C(n, 2)
对于 3 只猫:
n < 3:2^n - 1
n >= 3 : C(n, 1) + C(n, 2) + C(n, 3)
对于 4 只猫:
n < 4:2^n - 1
n >= 4 : C(n, 1) + C(n, 2) + C(n, 3) + C(n, 4)
从这里开始,我采用了简单递增 n 的简单方法,直到通过所需的数字楼层数。
Python 代码:
给出 (100, 2) = 14 的正确解。
对于任何希望检查一些不那么琐碎的事情的人,它给出 (1 000 000, 5) = 43。
这在 O(n) 中运行,其中 n 是问题的答案(猫越多越好)。
不过,我确信具有较高数学水平的人可以简化分段公式以在 O(1) 中进行计算。
I took a slightly different method to produce a solution.
I started by working out the maximum floor that could be covered using x cats and y guesses using the following method.
Start with 1 floor and keep increasing the number of guesses while keeping track of floors checked, which guess they were checked on and how many cats were remaining for each floor.
Repeat this up to y times.
This very inefficient code to compute the given answer but nonetheless useful for small number of cats / floors.
Python code:
For 2 cats the maximum floors that can be identified in x guesses is:
1, 3, 6, 10, 15, 21, 28...
For 3 cats:
1, 3, 7, 14, 25, 41, 63...
For 4 cats:
1, 3, 7, 15, 30, 56, 98...
After extensive research (mostly involving typing numbers sequences into OEIS) I noticed that the maximum floors for x follows a combination piecewise pattern.
For 2 cats:
n < 2 : 2^n - 1
n >= 2 : C(n, 1) + C(n, 2)
For 3 cats:
n < 3 : 2^n - 1
n >= 3 : C(n, 1) + C(n, 2) + C(n, 3)
For 4 cats:
n < 4 : 2^n - 1
n >= 4 : C(n, 1) + C(n, 2) + C(n, 3) + C(n, 4)
From here I took the easy approach of simple incrementing n until I pass the required number of floors.
Python code:
This gives the correct solution for (100, 2) = 14.
For anyone that wishes to check something less trivial, it gives (1 000 000, 5) = 43.
This runs in O(n) where n is the answer to the problem (the more cats the better).
However I'm sure a somebody with a higher level of mathematics could simplify the piecewise formulas to compute in O(1).
所有这些关于猫的疯狂谈论……这只是一个最小猜测(猫的数量)的数字问题。也不应该需要人为地(并且错误地)定义无穷大作为解决方案的一部分。该变量应该被命名为 upper-bound 或 max-try 等。
不过,问题定义(猫的事情)存在一些严重的问题,人们对虐待动物的可能性以及现实生活中提出的此类问题的许多方面做出反应,例如空气阻力、重力是加速度以及其他此类现实生活参数的问题。所以也许应该以完全不同的方式提出这个问题。
all this crazy talk about cats..and it's just a guess the number problem with minimum guesses (number of cats). there shouldn't be a need to artificially (and incorrectly) define infinity as part of the solution either. the variable should have been named upper-bound or max-try or some such.
the problem definition (the cat thing) has some serious issues though, with people responding to animal cruelty potential and also the many facets of such a problem posed in real life, e.g. air-drag, gravity is acceleration, and other such real life parameters of the problem. so perhaps it should have been asked in a totally different way.