窓から猫を投げる


150

猫がいる高層ビルにいるとします。猫は低い階の窓から落ちても生き残ることができますが、高床から投げられると死にます。最小限の試行回数で、猫が生き残ることができる最長の落下をどのようにして把握できますか?

明らかに、猫が1匹しかいない場合、直線的にしか検索できません。まず1階から猫を投げます。生き残った場合は2回目から投げます。やがて、f階から投げ出された猫は死ぬ。すると、f-1フロアが最大安全フロアであったことがわかります。

しかし、猫が複数いる場合はどうでしょうか。これで、ある種の対数検索を試すことができます。ビルドが100階建てで、猫が2匹いるとします。最初の猫を50階から投げ出して死んだ場合、50階を直線的に検索するだけで済みます。あなたが最初の試みのために低い階を選択した場合、あなたはさらに良いことができます。一度に20フロアの問題に取り組むことを選択し、最初の致命的なフロアが#50であるとします。その場合、最初の猫は20階と40階のフライトを生き延びてから60階で死亡します。41階から49階を個別に確認するだけです。これは合計12回の試行であり、バイナリ除去を使用しようとした場合に必要な50回よりもはるかに優れています。

一般的に、2匹の猫がいるn階建ての建物の場合、最善の戦略は何ですか?それは最悪の場合の複雑さですか?n階とm猫はどうですか?

すべての猫が同等であると仮定します。それらはすべて、所定のウィンドウからの落下によって生き残るか、または死亡します。また、すべての試みは独立しています:猫が転倒を生き延びた場合、それは完全に無害です。

これは宿題ではありませんが、学校の課題のために一度解決したかもしれません。今日、気まぐれな問題が頭に浮かんだだけで、その解決策を思い出せません。この問題の名前またはソリューションアルゴリズムの名前を知っている人がいる場合は、ボーナスポイントになります。


123
私は上記の方法で猫を使用することに反対します。犬に変更できますか?
ティロ

53
それはそれほど単純ではありません。調査が行われました(猫が誤って超高層ビルから落下し、投げられていない)。彼らが亡くなった一定の範囲と、彼らが生き残った***より高い***範囲がありました。彼らが自分の体を緊張させた方法についての何か。
アンドリューシェパード

5
私は15フィート以上のどこかで読んだことがある、猫は生き残る可能性が高い。この質問は、元ガールフレンドをドロップしたり、妻をしつこくしたりする場合に適しています。
Anthony Forloney、2010

34
2匹の猫から始める場合、数か月待ってからバイナリ検索を実行できます。または、その後数か月待って、「同時検索」を実行します。ヘルパーはすべてのフロアから同時に猫を投げることができます。その場合、生存している猫の数は、もちろん、投げることができる最大の階数です。 。
mjfgates 2010

10
ウサギの場合、「月」を「週」に変更します。
mjfgates 2010

回答:


70

nフロアとm猫の一般的なケースでは、少しのDP(動的プログラミング)を簡単に記述できます。

主な式、a[n][m] = min(max(a[k - 1][m - 1], a[n - k][m]) + 1) : for each k in 1..nは一目瞭然です。

  • 最初の猫がk階から投げ出されて死んだ場合、k - 1チェックする床(すべて以下k)とm - 1猫(a[k - 1][m - 1])が用意されました。
  • 猫が生き残った場合、n - k残りの階(上の階すべてk)にm猫が残っています。
  • 両者の最悪の場合には、従って、選択されるべきですmax
  • + 1 (猫が生き残ったかどうかにかかわらず)1つの試みを使用したという事実から来ています。
  • 可能な限りあらゆるフロアを試し、最良の結果を見つけますmin(f(k)) : for k in 1..n

100、2)に対するGaurav SaxenaのリンクからのGoogleの結果に同意します。

int n = 100; // number of floors
int m = 20; // number of cats
int INFINITY = 1000000;

int[][] a = new int[n + 1][m + 1];
for (int i = 1; i <= n; ++i) {
    // no cats - no game
    a[i][0] = INFINITY;
}

for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
        // i floors, j cats
        a[i][j] = INFINITY;

        for (int k = 1; k <= i; ++k) {
            // try throw first cat from k-th floor
            int result = Math.max(a[k - 1][j - 1], a[i - k][j]) + 1;
            a[i][j] = Math.min(a[i][j], result);
        }
    }
}

System.out.println(a[n][m]);

k別の配列に最もよく保存すれば、戦略(最初の猫を投げる方法)を簡単に見つけることができます。

O(n ^ 3)計算を含まない、より高速なソリューションもありますが、私はすでに少し眠くなっています。

編集
ええ、私は以前にこの問題を見た場所を覚えています


うーん、+ 1外にいる必要はありませんmin()か?あなたが言うように、試みが成功したかどうかにかかわらず、それはまだ試みです。
j_random_hacker

@j_random_hackerそれは何かを変えますか?の+1外に移動していminます。または、max:)の中に移動する
Nikita Rybak

@Nikita:ごめんなさい、あなたが書いたものをどういうわけか読み違えてしまいました-私によると、あなたが持っているものは正確に正しいです!+1。
j_random_hacker 2010年

これはGoogle Code Jamの「エッグドロップ問題」と同じであることに注意してください。大きな問題セットではN = 2000000000を使用するため、以下のO(n ^ 3)解では十分ではありません。code.google.com
codejam /

1
O(n)アルゴリズムについては、この新しい質問を参照してください。Google Code Jamの一番の答えはO(n)ですが、まだわかりません。stackoverflow.com/questions/4699067/...
ripper234

92

Radiolabの最近のエピソード(「Falling」について)によれば、猫は9階までに終末速度に達します。その後、それはリラックスし、傷つく可能性は低くなります。30日以上から転落した猫は無傷です。最も危険なフロアは5〜9階です。


16
猫の人として、この研究は除害事件後の動物病院の報告に基づいていることを指摘したいと思います。この調査で追加の猫が怪我をしたり、不便をかけたりすることはありませんでした。
Thilo

16
答えではなく、ビジネスドメインからの追加のコンテキストです。
ティロ

19
質問に値するだけの答えです。
Mark Ransom

2
これは、結果がlive = 1、die = 0の場合ではないことを示していますが、live = 1.0、die = 0.0、およびその間のすべてが確率です。また、発見する必要があるのは直線ではなく曲線です。
tadman

73
そのレポートの問題は選択バイアスです-死んだ猫を獣医に連れて行く人はいません。
吉内ニキ

10

猫がいる高層ビルにいるとします。猫は低い階の窓から落ちても生き残ることができますが、高床から投げられると死にます。最小限の試行回数で、猫が生き残ることができる最長の落下をどのようにして把握できますか?

この問題を解決するための最良の戦略は、物理法則を使用して、最初に仮定が真である確率を調査することです。

もしそうなら、あなたは猫が生き残る可能性が実際に地面までの距離が遠くなるほど増えることに気付くでしょう。もちろん、ペトロナスタワーなどのこれまでより高い建物から投げたと仮定します。エベレストなどのこれまでより高い山ではありません。

編集:
実際には、完成していないラクダの分布が表示されます。
最初に、猫が死ぬ可能性は低く(高度が非常に低い)、その後高くなります(高度が低くなります)。

地上の標高の関数としての猫の死亡確率のグラフは次のようになります
(ラクダの分布が終了していないため、3で終了)

代替テキスト

更新:
猫の終末速度は100 km / h(60mph)[= 27.7m / s = 25.4ヤード/ s]です。
人間の端末の速度は210 km / h(130mph)です。[= 75m / s = 68.58ヤード/ s]

終端速度ソース:
http : //en.wikipedia.org/wiki/Cat_righting_reflex

クレジット:
Goooooogle

後で確認する必要があります
http : //en.wikipedia.org/wiki/Terminal_velocity
http://www.grc.nasa.gov /WWW/K-12/airplane/termv.html



2
これは正しいです?確かに終末速度に到達すると、チャンスは変化しません-そして、私は猫が終末速度の落下に耐えることができるという印象を受けました。
ZoFreX 2010

4
@ZoFreX:もちろん可能です。最も致命的なのは、最終速度のすぐ下です。一方、たとえば10万マイル上から猫を落とすと、猫は真空で死んだ後、落下して生きるよりも大気中で燃えやすくなります。
David Thornley、

1
それらのウサギの耳はそのグラフにありますか?
ninjalj 2010

1
@ZoFreX:角運動量。猫の体のデザインと猫の回転スキルによる角運動量のため、猫は常に足に着地します。しかし、それはそれでも方向転換する時間が必要であることを意味します。時間があるほど(==>標高が高いほど)、猫が足に着地する可能性が高くなります(==>頭に着地するのとは対照的に、生存の可能性が劇的に増加します)。しかし、そうです、最終的な速度に達した後、確率は同じままです。猫が最終速度の低下に耐えられる可能性はかなり高いと思います。少なくとも、私のものはスクラッチなしでトイレの窓(約20m)から飛び出しました。
Stefan Steiger、

8

私はまずこの問題をSteven SkienaのAlgorithm Design Manual(演習8.15)で読みました。それは動的プログラミングに関する章に続きましたが、戦略の正確な境界を証明するために動的プログラミングを知る必要はありません。最初に問題のステートメント、次に以下のソリューションです。

卵は十分な高さから落とすと壊れます。n階建ての建物の場合、f階から落下した卵は壊れますが、f-1階から落下した卵は生き残るようなf床が必要です。(卵がいずれかの床から壊れた場合、f = 1と表示します。卵がいずれかの床から生き残った場合、f = n + 1と表示します)。

あなたはクリティカルフロアを見つけようとしますf。実行できる唯一の操作は、卵を床から降ろして何が起こるかを確認することです。k個の卵から始めて、できるだけ数回卵を落とそうとします。壊れた卵は再利用できません(無傷の卵は再利用できます)。E(k、n)を常に十分な卵の糞の最小数とする。

  1. E(1、n)= nであることを示します。
  2. それを示してくださいE(k,n) = Θ(n**(1/k))
  3. E(k、n)の繰り返しを見つけます。E(k、n)を見つけるための動的プログラムの実行時間はどれくらいですか?

たまご1個

最初から各フロアから卵をドロップすると、(最悪の)n回の操作でクリティカルフロアが見つかります。

より速いアルゴリズムはありません。任意のアルゴリズムの任意の時点で、卵が壊れないように見られている最も高い床をgにします。アルゴリズムは、より高いフロアh> g + 1の前にフロアg + 1をテストする必要があります。それ以外の場合、卵がフロアhから離脱した場合、f = g + 1とf = hを区別できませんでした。

卵2個

最初に、n = r ** 2が完全な正方形である、k = 2の卵の場合を考えてみましょう。O(sqrt(n))時間を要する戦略を次に示します。最初に、r階単位で最初の卵を落とします。最初の卵が壊れたとき、たとえばfloor arで、臨界床fがでなければならないことがわかります(a-1)r < f <= ar。次に、各フロアから2番目の卵をドロップし(a-1)rます。2番目の卵が壊れると、クリティカルフロアが見つかりました。各卵を最大でr回削除したので、このアルゴリズムは最悪の2r演算、つまりΘ(sqrt(n))を取ります。

nが完全な正方形でない場合は、r =としceil(sqrt(n)) ∈ Θ(sqrt(n))ます。アルゴリズムはremains(sqrt(n))のままです。

アルゴリズムが少なくともsqrt(n)時間かかることを証明します。より高速なアルゴリズムがあるとします。最初の卵が落ちる順番を考えます(壊れない限り)。sqrt(n)よりもドロップが少ないため、少なくともn / sqrt(n)の間隔が必要です。これはsqrt(n)です。fがこの間隔内にある場合、アルゴリズムは2番目の卵でそれを調査する必要があります。これは、床ごとに1卵の場合を思い出して行う必要があります。矛盾。

k卵

2つの卵について提示されたアルゴリズムは、k個の卵に簡単に拡張できます。一定の間隔で各卵をドロップします。これは、nのk乗根の累乗と見なされます。たとえば、n = 1000およびk = 3の場合、最初の卵で100階、2番目の卵で10階、最後の卵で1階の検索間隔。

同様に、Θ(n**(1/k))k = 2の証明から帰納することで、アルゴリズムが高速でないことを証明できます。

正確なソリューション

最初の卵(床g)をどこにドロップするかを最適化することにより、再発を推測します。これは、小さいパラメーターの最適解を知っていると仮定しています。卵が壊れたら、下のg-1階でk-1の卵を探索します。卵が生き残った場合、k個の卵を探索するための床がngあります。悪魔は私たちにとって最悪のものを選びます。したがって、k> 1の場合、繰り返し

E(k,n) = min(max(E(k,n-g), E(k-1,g))) minimised over g in 1..n

私がk個の卵を持っているO(k*n**(1/k))場合、最悪の場合のランタイムはなぜですか?最悪の場合、私はn**(1/k) 正確にk何度も通過しなければならないので。
Rakete1111 2018

2

これは、「同じ猫」を使用していることを前提としていますか?

あなたは数学的にそれに取り組むことができますが、それは数学の良いことです...正しい仮定で、0は1に等しいことができます(0の大きな値の場合)。

実用的には「似たような猫」は手に入りますが、「同じ猫」は手に入りません。

経験的に回答を決定することもできますが、統計的に意味のない回答になるほど統計的に十分な違いがあると思います。

「同じ猫」を使用することもできますが、最初のドロップ後は同じ猫ではなくなったため、これは機能しません。(同様に、同じ川に2度踏み込むことはできません)

または、非常に短い間隔でサンプリングして、猫の健康状態を集計し、猫が「ほぼ生存」している高さを見つけることができます(「プリンセスブライド」の「ほとんど死んでいる」とは対照的です)。猫は平均して(最後の間隔まで)生存します。

私は元の意図から逸脱していると思いますが、経験的なルートを進んでいる場合は、できるだけ高いところから始め、統計的に生き残るまで高さが低くなるにつれて猫を落とし続けることに投票します。そして、生き残った猫を再テストして確認します。


0

少し異なる方法でソリューションを作成しました。

私は、次の方法を使用して、x猫とy推測を使用して、カバーできる最大の床を計算することから始めました。

1つのフロアから始め、チェックされたフロア(チェックされた推測と各フロアに残っている猫の数)を追跡しながら推測の数を増やし続けます。
これをy回まで繰り返します。

与えられた答えを計算するためのこの非常に非効率的なコードですが、それでも少数の猫/床に役立ちます。

Pythonコード:

def next_step(x, guess):
  next_x = []
  for y in x:
    if y[0] == guess:
      if y[1] != 1:
        next_x.append((guess+1, y[1] - 1))
    next_x.append(y)
    if y[0] == guess:
      next_x.append((guess+1, y[1]))
  return next_x

x = [(1, TOTAL_NUM_CATS)]
current_floor = 1
while len(x) <= TOTAL_NUM_FLOORS:
  x = next_step(x, current_floor)
  current_floor += 1
  print len(x)

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コード:

def find_smallest(floors, eggs):
  maximum_floors = 0
  n = 0
  while maximum_floors < floors:
    maximum_floors = 0
    n += 1
    if n < eggs:
      maximum_floors = 2**n - 1
    else:
      count = 0
      for x in xrange(1, eggs+1):
        maximum_floors += combination(n, x)
  print n

これは(100、2)= 14の正しい解を与えます。
ささいなことをチェックしたい人にとっては、(1 000 000、5)= 43を与えます。

これはO(n)で実行されます。nは問題の答えです(猫が多いほど良い)。
しかし、より高いレベルの数学を持つ誰かがO(1)で計算するために区分的公式を簡略化できると私は確信しています。


0
O(m*(n^(1/m))) algorithm.

Let 'x' be the maximum number of attempts needed.  

m = 1 => linear => x=n

m = 2:  
Let the floors be split into 'k' partitions. The first cat is thrown at the end of each partition (max 'k' times). 
When it dies, the second cat is used to go up from the beginning of this partition.   
x = k + n/k.   
Minimize x by diff wrt k and setting = 0, to get k = n^(1/2) and x = 2 * n^(1/2).

m = 3:  
x = k + 2*(y^(1/2)), where y = n/k  
diff wrt x and set = 0, to get k = n^(1/3) and x = 3 * n^(1/3)

for general m:  
x = m * n^(1/m). 

-1

これについてはGoogleブログスポットを読むことはできません(blogwallのおかげです)。しかし、ストレートバイナリスタイルの検索が最適だとは思いません。その理由は、バイナリ検索は、探している答えがリスト内のインデックスインデックスにある可能性が等しいという概念に基づいているためです。しかし、この場合はそうではありません。この場合、答えは範囲の一方の端に近い確率がもう一方の確率よりも高くなります。これを検索に組み込む方法はわかりませんが、興味深い考えです。


1
質問は最良の最悪のケースを求めていると思うので、すべてのフロアが可能な限り、分布は関係ありません。
Steve Jessop、

-1

猫についてのこのすべてのクレイジーな話..そしてそれは最小の推測(猫の数)での数の問題です。ソリューションの一部として人工的に(そして誤って)無限大を定義する必要もないはずです。変数は、upper-boundまたはmax-tryなどの名前が付けられているはずです。問題の定義(猫のこと)にはいくつかの深刻な問題がありますが、人々は動物の残虐行為の可能性に対応し、また、空気抵抗、重力は加速、その他の実生活パラメーターなど、実生活でもたらされるそのような問題の多くの側面を備えています。問題の。したがって、おそらくまったく異なる方法で要求されたはずです。


FWIW偽装された現実の問題である可能性があります。バージョン1234で失敗したが、バージョン42で機能した自動テストがあるとします。猫は1234で死んでいますが、バージョン42で生きています。どのリビジョンがそれを殺しましたか?たとえば42から43への更新が迅速かつ簡単だが、新しいバージョンをチェックアウトして再構築することが難しい場合、これは猫の問題のように見え始めます。
mcdowella
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.