Kedileri pencerelerden atma


150

Bir kedi ile yüksek bir binada olduğunuzu düşünün. Kedi düşük katlı bir pencereden düşerek hayatta kalabilir, ancak yüksek bir yerden atılırsa ölecektir. En az sayıda denemeyi kullanarak kedinin hayatta kalabileceği en uzun damlayı nasıl anlayabilirsiniz?

Açıkçası, sadece bir kediniz varsa, sadece doğrusal olarak arama yapabilirsiniz. İlk önce kediyi birinci kattan atın. Hayatta kalırsa, ikincisinden atın. Sonunda, f katından atıldıktan sonra kedi ölecek. Daha sonra biliyorsunuz ki f-1 katı maksimum güvenli zemin.

Peki ya birden fazla kediniz varsa? Artık bir çeşit logaritmik aramayı deneyebilirsiniz. Yapının 100 katlı olduğunu ve iki özdeş kedinizin olduğunu varsayalım. İlk kediyi 50. kattan atarsanız ve ölürse, o zaman sadece 50 kat doğrusal olarak arama yapmanız gerekir. İlk denemeniz için bir alt kat seçerseniz daha da iyisini yapabilirsiniz. Diyelim ki bir seferde 20 kat sorunu çözmeyi seçtiniz ve ilk ölümcül kat # 50. Bu durumda, ilk kediniz 60. kattan ölmeden önce 20 ve 40. katlardaki uçuşlarda hayatta kalacaktır. 41'den 49'a kadar olan katları tek tek kontrol etmeniz yeterlidir. Bu, toplam 12 denemedir, ki bu, ikili elemeyi kullanmaya çalışsaydınız, ihtiyacınız olan 50'den çok daha iyidir.

Genel olarak, en iyi strateji nedir ve 2 kedili n katlı bir bina için en kötü durum karmaşıklığı nedir? N kat ve m kediler için ne dersiniz?

Tüm kedilerin eşdeğer olduğunu varsayın: hepsi belirli bir pencereden düşerek hayatta kalacak veya ölecek. Ayrıca, her girişim bağımsızdır: bir kedi bir düşüşten kurtulursa, tamamen zarar görmez.

Bu ev ödevi değil, bir kez okul ödevi için çözmüş olabilirim. Bugün kafamda ortaya çıkan tuhaf bir problem ve çözümü hatırlamıyorum. Bu sorunun veya çözüm algoritmasının adını bilen bonus puanları.


123
Kedileri tarif edilen şekilde kullanmaya itiraz ediyorum. Bunu köpeklerle değiştirebilir miyiz?
Thilo

53
O kadar basit değil. Çalışmalar yapıldı (kazara gökdelenlerden düşen kediler atılan değil). Öldükleri belirli bir aralık vardı ve hayatta kaldıkları yerden *** daha yüksek bir aralık vardı. Vücutlarını nasıl gerdiklerine dair bir şey.
Andrew Shepherd

5
15ft veya üzeri bir yerde okudum, kedilerin hayatta kalma şansı daha fazla. Eski sevgili ve / veya nagging eşleri düşürüyor olsaydık bu soru daha uygun olurdu.
Anthony Forloney

34
İki kedi ile başlarsanız, sadece birkaç ay bekleyip ikili arama yapabilirsiniz. Ya da birkaç ay sonra bekleyin ve "eşzamanlı arama" yapın, burada her kattan aynı anda kedileri atmak için yardımcılar alırsınız - bu durumda hayatta kalan kedilerin sayısı elbette onlardan atabileceğiniz en yüksek kat sayısıdır. .
mjfgates

10
Tavşanlar için "ay" ı "hafta" olarak değiştirin.
mjfgates

Yanıtlar:


70

N kat ve m kedilerin genel durumu için kolayca küçük bir DP (dinamik programlama) yazabilirsiniz.

Ana formül, a[n][m] = min(max(a[k - 1][m - 1], a[n - k][m]) + 1) : for each k in 1..naçıklayıcı olmalıdır:

  • İlk kedi k-zeminden atılır ve ölürse, şimdi k - 1kontrol etmek için zeminlerimiz var (aşağıda k) ve m - 1kediler ( a[k - 1][m - 1]).
  • Kedi hayatta kalırsa, kalan n - kkatlar (yukarıdaki tüm katlar k) ve hala mkediler vardır.
  • Bu nedenle, en kötü ikisinin seçilmesi gerekir max.
  • + 1 sadece bir denemeyi kullandığımız gerçeğinden geliyor (kedinin hayatta olup olmadığına bakılmaksızın).
  • Bu nedenle, en iyi sonucu bulmak için mümkün olan her zemini deneriz min(f(k)) : for k in 1..n.

Google, Gaurav Saxena'nın (100, 2) bağlantısından aldığı sonuca katılıyor .

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]);

kBaşka bir dizide en iyi şekilde tasarruf ederseniz, stratejiyi (ilk kediyi nasıl atacağınızı) kolayca bulabilirsiniz .

Ayrıca daha hızlı bir çözüm var, O (n ^ 3) hesaplamaları içermiyor, ama zaten biraz uykum var.

düzenlemek
Oh yeah, I get this problem where seen problem daha önce .


Hmm, + 1dışarıda olması gerekmiyor min()mu? Kendiniz söylediğiniz gibi, girişim başarılı olsun ya da olmasın, hala bir girişimdir.
j_random_hacker

@j_random_hacker Bir şey değiştiriyor mu? Hareketli +1dışında min. Veya içinde hareket max:)
Nikita Rybak

@Nikita: Üzgünüm bir şekilde yazdıklarını yanlış okudum - sahip olduğun şey bana göre tam olarak doğru! +1.
j_random_hacker

Bunun Google Code Jam'in "Egg Drop problemi" ile aynı olduğunu unutmayın. Aşağıdaki O (n ^ 3) çözümü yeterince iyi değil çünkü büyük sorun kümesi N = 2000000000. code.google.com/codejam/contest/dashboard?c=32003#s=p2
ripper234

1
O (n) algoritması için bu yeni soruya bakın. Google Code Jam'in en iyi yanıtı O (n), ama henüz anlamadım. stackoverflow.com/questions/4699067/…
ripper234

92

Göre ( "Falling" hakkında) Radiolab son bölümünün , bir kedi 9. kattaki terminal hızına ulaşır. Bundan sonra rahatlar ve zarar görmesi daha az olasıdır. 30'un üstünden düştükten sonra tamamen yaralanmamış kediler var. En riskli katlar 5. ila 9. arasındadır.


16
Bir kedi insanı olarak, bu çalışmanın defenestrasyon olaylarından sonra hayvan hastanesi raporlarına dayandığını belirtmek isterim. Bu sorguda başka hiçbir kedi yaralanmamış veya rahatsız edilmemiştir.
Thilo

16
Yanıt değil, yalnızca işletme alanından bazı ek bağlamlar.
Thilo

19
Sorunun hak ettiği kadar çok cevap var.
Mark Ransom

2
Bu sadece sonuç olarak canlı = 1, die = 0 vakası olmadığını gösterir, ancak canlı = 1.0, die = 0.0 ve daha fazlası her şey olasılıklardır. Ayrıca keşfedilmesi gereken bir çizgi değil, bir eğri.
tadman

73
Bu rapordaki sorun seçim önyargısıdır - kimse veterinere ölü bir kedi götürmez.
Niki Yoshiuchi

10

Bir kedi ile yüksek bir binada olduğunuzu düşünün. Kedi düşük katlı bir pencereden düşerek hayatta kalabilir, ancak yüksek bir yerden atılırsa ölecektir. En az sayıda denemeyi kullanarak kedinin hayatta kalabileceği en uzun damlayı nasıl anlayabilirsiniz?

Bu sorunu çözmek için en iyi strateji, fizik yasasını kullanarak, varsayımlarınızın ilk başta doğru olma olasılığını araştırmaktır.

Eğer bunu yaparsanız, kedinin hayatta kalma şansının aslında yere olan mesafe ne kadar artarsa ​​fark edersiniz. Tabii ki, petronas kuleleri gibi daha yüksek bir binadan attığınızı varsayarsak, everest dağı gibi daha yüksek bir dağdan değil.

Düzenleme:
Aslında, tamamlanmamış bir deve dağılımı görürsünüz.
İlk olarak, kedinin ölme olasılığı düşüktür (çok düşük irtifa), daha sonra yükselir (alçak irtifa), sonra tekrar daha düşük (daha yüksek rakım) ve sonra tekrar daha yüksek (çok yüksek rakım).

Yerden yüksekliğin bir fonksiyonu olarak kedinin ölme olasılığı grafiği şu şekildedir:
(3'te bitir, çünkü bitmemiş deve dağılımı)

alternatif metin

Güncelleme:
Bir kedinin terminal hızı 100 km / s (60mph) [= 27,7m / s = 25,4 yard / s].
İnsan terminal hızı 210 km / s'dir (130mph). [= 75m / s = 68,58 yard / s]

Terminal hız kaynağı:
http://en.wikipedia.org/wiki/Cat_righting_reflex

Kredi:
Goooooogle

Daha sonra doğrulamam gerekiyor:
http://en.wikipedia.org/wiki/Terminal_velocity
http://www.grc.nasa.gov /WWW/K-12/airplane/termv.html



2
Bu doğru mu? Kuşkusuz terminal hıza ulaşıldığında, şans değişemez - ve ben bir kedinin terminal hız düşüşünden kurtulabileceği izlenimi altındaydım.
ZoFreX

4
@ZoFreX: Elbette yapabilirler, en ölümcül olan terminal hızının hemen altında. Öte yandan, yüz bin mil kadar bir kediyi bırakın ve kedinin boşluktan öldükten sonra atmosferde yanması ve düşmekten daha olasıdır.
David Thornley

1
Bu grafikteki tavşan kulakları mı?
ninjalj

1
@ZoFreX: Açısal momentum. Bir kedi, kedinin gövde tasarımı ve kedinin dönüş becerileri nedeniyle açısal momentum nedeniyle her zaman ayaklarının üzerine iner. Ama bu hala dönmesi gereken zaman anlamına geliyor. Ne kadar fazla zaman olursa (==> rakım o kadar yüksek olur), kedinin ayağa kalkması daha olasıdır (==> hayatta kalma şansı, örneğin kafaya iniş yerine, önemli ölçüde artar). Ama haklısın, terminal hızına ulaştıktan sonra olasılık aynı kalır. Bir kedinin bir terminal hız düşüşünde hayatta kalabileceğini söyleyebilirim, en azından benim banyo penceresinden (yaklaşık 20m) bir çizik olmadan atladı.
Stefan Steiger

8

Bu problemi önce Steven Skiena'nın Algoritma Tasarım El Kitabında okudum (alıştırma 8.15). Dinamik programlama ile ilgili bir bölüm izledi, ancak stratejiye kesin sınırları kanıtlamak için dinamik programlama bilmenize gerek yok . Önce problem açıklaması, sonra aşağıdaki çözüm.

Yumurtalar yeterince yükseklerden düştüğünde kırılır. N katlı bir bina göz önüne alındığında, f katından yumurta düştüğü, ancak f-1 katından bırakılan yumurtaların hayatta kalabileceği bir kat olmalıdır. (Yumurta herhangi bir yerden koparsa, f = 1 diyeceğiz. Yumurta herhangi bir yerden hayatta kalırsa, f = n + 1 diyeceğiz).

Kritik katı bulmaya çalışıyorsunuz f. Yapabileceğiniz tek işlem, yumurtayı bir zeminden bırakmak ve ne olduğunu görmek. K yumurta ile başlıyorsunuz ve mümkün olduğunca az kez yumurta bırakmaya çalışıyorsunuz. Kırık yumurtalar tekrar kullanılamaz (bozulmamış yumurtalar olabilir). E (k, n) her zaman yeterli olacak minimum yumurta bırakma sayısı olsun.

  1. E (1, n) = n olduğunu gösterin.
  2. Göster şunu E(k,n) = Θ(n**(1/k)).
  3. E (k, n) için bir nüks bul. E'yi bulmak için dinamik programın çalışma süresi nedir (k, n)?

Sadece 1 yumurta

İlk aşamadan başlayarak her bir kattan yumurtayı düşürmek (en kötü) n operasyonlarında kritik zemini bulacaktır.

Daha hızlı bir algoritma yoktur. Herhangi bir algoritmada herhangi bir zamanda, yumurtanın kırılmadığı görülen en yüksek zemini bırakın. Algoritma g + 1 katını h> g + 1 katlarından önce test etmelidir, aksi takdirde yumurta h katından kopacaksa f = g + 1 ve f = h arasında ayrım yapamazdı.

2 yumurta

İlk olarak, n = r ** 2 mükemmel bir kare olduğunda k = 2 yumurta kasasını düşünelim. İşte O (sqrt (n)) zamanını alan bir strateji. İlk yumurtayı r katları halinde bırakarak başlayın. İlk yumurta kırıldığında, diyelim ki katta ar, kritik katın f olması gerektiğini biliyoruz (a-1)r < f <= ar. Daha sonra her bir yerden ikinci yumurtayı başlıyoruz (a-1)r. İkinci yumurta kırıldığında kritik zemini bulduk. Her yumurtayı en fazla r zamanında bıraktık, bu nedenle bu algoritma en kötü 2r işlem alıyor, ki bu Θ (sqrt (n)).

N mükemmel bir kare olmadığında, r = değerini alın ceil(sqrt(n)) ∈ Θ(sqrt(n)). Algoritma Θ (sqrt (n)) olarak kalır.

Herhangi bir algoritmanın en az sqrt (n) zaman aldığını kanıtlayın. Daha hızlı bir algoritma olduğunu varsayalım. İlk yumurtayı düşürdüğü zemin sırasını düşünün (kırılmadığı sürece). Sqrt (n) 'den daha az düştüğü için, en az n / sqrt (n) olan ve sqrt (n) olan bir aralık olmalıdır. F bu aralıktayken, algoritmanın ikinci yumurta ile araştırması gerekir ve bu 1 yumurtalık vakayı hatırlatarak kat kat yapılmalıdır. Çelişki.

k yumurta

2 yumurta için sunulan algoritma kolayca k yumurtalarına genişletilebilir. Her yumurtayı n'nin kth kökünün gücü olarak alınması gereken sabit aralıklarla bırakın. Örneğin, n = 1000 ve k = 3 için, ilk yumurta ile 100, ikinci yumurta ile 10 ve son yumurta ile 1 kat aralıkları arayın.

Benzer şekilde, Θ(n**(1/k))k = 2 kanıtından yola çıkarak hiçbir algoritmanın daha hızlı olmadığını kanıtlayabiliriz.

Kesin çözüm

Daha küçük parametreler için en uygun çözümleri bildiğimizi varsayarak, ilk yumurtayı nereye bırakacağımızı (kat g) optimize ederek nüksü çıkarırız. Yumurta kırılırsa, k-1 yumurtalarını keşfetmek için aşağıdaki g-1 katlarımız var. Yumurta hayatta kalırsa, k yumurtaları keşfetmek için yukarıdaki zeminlerimiz var. Şeytan bizim için en kötüyü seçer. Böylece k> 1 için nüks

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

K yumurtam varsa O(k*n**(1/k)), en kötü durum için çalışma zamanı neden olmasın ? En kötü durumda ben n**(1/k) tam olarak kzaman geçmesi gerekir .
Rakete1111

2

Bu, "Aynı Kedi" yi kullandığınızı varsaymıyor mu?

Matematiksel olarak yaklaşabilirsiniz, ancak bu matematikle ilgili güzel bir şeydir ... doğru varsayımlarla, 0 1'e eşit olabilir (0'ın büyük değerleri için).

Pratik bir bakış açısından, 'Benzer Kediler' elde edebilirsiniz, ancak "Aynı Kedi" alamazsınız.

Cevabı ampirik olarak belirlemeye çalışabilirsiniz, ancak cevabın istatistiksel olarak anlamsız olacağı kadar istatistiksel farklılıkların olacağını düşünürdüm.

"Aynı Kedi" yi kullanmayı deneyebilirsiniz, ancak ilk damladan sonra artık aynı kedi olmadığı için bu işe yaramaz. (Benzer şekilde, onecan asla aynı nehre iki kez girmez)

Ya da, kedinin sağlığını toplayabilir, son derece yakın aralıklarla örnekleyebilir ve kedinin "çoğunlukla canlı" olduğu yükseklikleri bulabilirsiniz ("Prenses Gelin" den "çoğunlukla ölü" ye karşı). Kediler ortalama olarak hayatta kalacaktır (son aralığa kadar).

Sanırım asıl niyetten uzaklaştım, ama ampirik rotaya gidiyorsanız, mümkün olduğunca yükseğe başlamak ve istatistiksel olarak hayatta kalana kadar yükseklik azaldıkça kedileri düşürmeye devam etmek için oy veriyorum. Ve sonra emin olmak için hayatta kalan kedileri yeniden test edin.


0

Bir çözüm üretmek için biraz farklı bir yöntem kullandım.

Aşağıdaki yöntemi kullanarak x kediler ve y tahminleri kullanılarak kaplanabilecek maksimum zemini çalışarak başladım .

1 kat ile başlayın ve katları kontrol altında tutarken tahmin sayısını artırmaya devam edin, hangi kontrol edildiğini ve her kat için kaç kedinin kaldığını tahmin edin.
Bunu y defaya kadar tekrarlayın .

Verilen cevabı hesaplamak için bu çok verimsiz kod ama yine de az sayıda kedi / kat için yararlıdır.

Python kodu:

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 kedi için x tahmininde tanımlanabilecek maksimum kat sayısı:
1, 3, 6, 10, 15, 21, 28 ...

3 kedi için:
1, 3, 7, 14, 25, 41, 63 ...

4 kedi için:
1, 3, 7, 15, 30, 56, 98 ...

Sonra kapsamlı bir araştırma (çoğunlukla içine yazma numaraları dizileri kapsayan OEIS I için maksimum kat fark) x bir şu kombinasyon parçalı deseni.

2 kedi için:
n <2: 2 ^ n - 1
n> = 2: C (n, 1) + C (n, 2)

3 kedi için:
n <3: 2 ^ n - 1
n> = 3: C (n, 1) + C (n, 2) + C (n, 3)

4 kedi için:
n <4: 2 ^ n - 1
n> = 4: C (n, 1) + C (n, 2) + C (n, 3) + C (n, 4)

Buradan, gerekli kat sayısını geçene kadar basit artan n'nin kolay yaklaşımını aldım.

Python kodu:

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

Bu, (100, 2) = 14
için doğru çözümü verir. Daha az önemsiz bir şeyi kontrol etmek isteyen herkes için (1000 000, 5) = 43 verir.

Bu, n'nin sorunun cevabı olduğu O (n) 'de çalışır (daha fazla kedi daha iyidir).
Ancak daha yüksek matematik seviyesine sahip birinin parçalı formülleri O (1) 'de hesaplamak için basitleştirebileceğinden eminim.


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

Bu konuda google blogspot okuyamıyorum (blogwall çalışmaları sayesinde) ama düz bir ikili tarzı arama en iyi olacağını düşünmüyorum. Bunun nedeni, ikili aramanın, aradığınız yanıtın listedeki herhangi bir dizin dizininde olma şansının eşit olduğu fikrini temel almasıdır. Ancak bu durumda bu doğru değildir. Bu durumda cevap aralığın bir ucuna diğerinden daha yakın olma olasılığı daha yüksektir. Bunu araştırmaya nasıl dahil edeceğime dair hiçbir fikrim yok, ama ilginç bir düşünce.


1
Bence soru en kötü durumu soruyor, bu yüzden her kat mümkün olduğu sürece dağılım önemsiz.
Steve Jessop

-1

kediler hakkında tüm bu çılgın konuşma ... ve bu sadece bir tahmin asgari tahminler ile sayı sorunu (kedi sayısı). Sonsuzluğu yapay olarak (ve yanlış) çözümün bir parçası olarak tanımlamaya gerek olmamalıdır. değişkenin üst sınırı veya max-try veya bir kısmı olarak adlandırılmış olması gerekir. sorun tanımı (kedi şeyinin) bazı ciddi sorunları vardır, insanlar hayvan zulüm potansiyeline cevap verir ve aynı zamanda gerçek hayatta ortaya çıkan böyle bir sorunun birçok yönünü, örneğin hava sürükleme, yerçekimi ivmedir ve diğer gerçek yaşam parametreleri problemin. bu yüzden belki de tamamen farklı bir şekilde sorulmalıydı.


FWIW gizlenmiş bir gerçek yaşam sorunu olabilir. Varsayalım ki, sürüm 1234'te başarısız olan ancak sürüm 42'de çalışan bir otomatik testiniz var. Kedi 1234'te öldü, ancak sürüm 42'de yaşıyor. Hangi revizyonu öldürdü? Örneğin 42'den 43'e güncelleme hızlı ve kolaydır, ancak yeni bir sürümü kontrol etmek ve yeniden oluşturmak zorsa, bu kedi problemine çok benzemeye başlar.
mcdowella
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.