Выбрасывание кошек из окон

Представьте, что вы находитесь в высоком здании с кошкой. Кошка может выдержать падение из окна с низкой историей, но умрет, если ее выбросят с высокого этажа. Как вы можете найти самое длинное падение, которое может выдержать кошка, используя наименьшее количество попыток?

Очевидно, если у вас есть только одна кошка, вы можете искать только линейно. Сначала бросьте кошку с первого этажа. Если он выживет, выбросьте его со второго. В конце концов, после того, как он будет выброшен с пола f, кошка умрет. Затем вы знаете, что пол f-1 был максимальным безопасным полом.

Но что, если у вас есть более чем одна кошка? Теперь вы можете попробовать какой-то логарифмический поиск. Скажем, что сборка имеет 100 этажей, и у вас есть две одинаковые кошки. Если вы выбросите первого кота из 50-го этажа, и он умрет, вам придется искать только 50 этажей. Вы можете сделать еще лучше, если вы выберете нижний этаж для первой попытки. Скажите, что вы решили решить проблему по 20 этажей за раз и что первый роковой этаж №50. В этом случае ваш первый кот выдержит полеты с этажей 20 и 40, прежде чем умереть с 60-го уровня. Вам просто нужно проверять полы с 41 по 49 индивидуально. Это всего 12 попыток, которые намного лучше, чем 50, которые вам понадобятся, если бы вы попытались использовать бинарное устранение.

В целом, какая лучшая стратегия и наихудшая сложность для n-этажного здания с двумя кошками? Как насчет n этажей и м кошек?

Предположим, что все кошки эквивалентны: все они выживут или умрут от падения из данного окна. Кроме того, каждая попытка является независимой: если кошка переживает падение, она полностью невредима.

Это не домашнее задание, хотя я, возможно, решил его для школьного задания один раз. Это просто капризная проблема, которая появилась сегодня в моей голове, и я не помню решение. Бонусные баллы, если кто-либо знает название этой проблемы или алгоритм решения.

Ответ 1

Вы можете легко написать небольшое DP (динамическое программирование) для общего случая n этажей и m кошек.

Основная формула 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 происходит от того факта, что мы только что использовали одну попытку (независимо от того, выжила ли кошка или нет).
  • Мы стараемся всякий раз найти лучший результат, следовательно min(f(k)) : for k in 1..n.

Это согласуется с результатом Google из ссылки Gaurav Saxena для (100, 2).

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), но я уже немного сонный.

изменить
О да, Я помню, где я видел эту проблему до.

Ответ 2

Согласно недавнему эпизоду Radiolab (около "Falling" ), кошка достигает конечной скорости на 9-м этаже. После этого он расслабляется и с меньшей вероятностью будет ранен. После падения с 30-го года есть совершенно неповрежденные кошки. Самые рискованные этажи - от 5 до 9.

Ответ 3

Представьте, что вы находитесь в высоком здании с кошкой. Кошка может выдержать падение из окна с низкой историей, но умрет, если ее выбросят с высокого этажа. Как вы можете найти самое длинное падение, которое может выдержать кошка, используя наименьшее количество попыток?

Лучшей стратегией для решения этой проблемы является исследование, используя закон физики, вероятность того, что ваши предположения будут истинными в первую очередь.

Если бы вы это сделали, вы бы поняли, что шансы на выживание кошки фактически увеличивают расстояние до земли. Конечно, предполагая, что вы выбросите его из все более высокого здания, такого как башни петронов, а не на более высокую гору, например на гору.

Изменить:
На самом деле, вы увидите незаконченное распределение верблюдов.
Во-первых, вероятность смерти кошки низкая (очень низкая высота), затем она становится выше (малая высота), затем снова ниже (более высокая высота), а затем снова выше (очень большая высота).

График вероятности смерти кошки как функции высоты над землей выглядит следующим образом:
(финишировать на 3, потому что незаконченное распределение верблюда)

alt text

Обновление:
Скорость полета кошки составляет 100 км/ч (60 миль в час) [= 27,7 м/с = 25,4 м/с].
Скорость полета человека составляет 210 км/ч (130 миль в час). [= 75 м/с = 68,58 ярдов/с]

Источник скорости терминала:
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


Ответ 4

Я впервые прочитал эту проблему в Руководстве по разработке алгоритма Стивена Скиена (упражнение 8.15). Он последовал за главой динамического программирования, но вам не нужно знать динамическое программирование, чтобы доказать точные границы стратегии. Сначала сформулируйте задачу, затем решение ниже.

Яйца ломаются при падении с достаточно большой высоты. С учетом n-этажного здания должен быть пол f, так что яйца выпадали из пола, но яйца, выпавшие из пола f-1, выживают. (Если яйцо разбивается с любого пола, мы скажем f = 1. Если яйцо выживет с любого пола, мы скажем f = n + 1).

Вы пытаетесь найти критический пол f. Единственная операция, которую вы можете выполнить, - сбросить яйцо с пола и посмотреть, что произойдет. Вы начинаете с k яиц и пытаетесь сбросить яйца как можно меньше. Сломанные яйца не могут быть повторно использованы (интактные яйца могут). Пусть E (k, n) - минимальное количество яичных помет, которое всегда будет достаточным.

  • Покажите, что E (1, n) = n.
  • Показать, что E(k,n) = Θ(n**(1/k)).
  • Найти повторение для E (k, n). Каково время работы динамической программы для поиска E (k, n)?

Только 1 яйцо

Отбрасывание яйца с каждого пола, начиная с первого, найдет критический пол в (по крайней мере) n операциях.

Не существует более быстрого алгоритма. В любой момент в любом алгоритме пусть g - самый верхний этаж, из которого видно, что яйцо не сломается. Алгоритм должен проверять пол g + 1 перед любым верхним этажом h > g + 1, иначе, если яйцо должно было сломаться от пола h, оно не могло различать f = g + 1 и f = h.

2 яйца

Сначала рассмотрим случай яйца k = 2, когда n = r ** 2 - идеальный квадрат. Здесь стратегия, которая принимает время O (sqrt (n)). Начните с отбрасывания первого яйца поэтапно. Когда первое яйцо разбивается, скажем, на этаже ar, мы знаем, что критический пол f должен быть (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 яиц. Бросьте каждое яйцо с постоянными интервалами, которые следует воспринимать как силы k-го корня из n. Например, для n = 1000 и k = 3 интервалы поиска 100 этажей с первым яйцом, 10 со вторым яйцом и 1 с последним яйцом.

Аналогично, мы можем доказать, что алгоритм не быстрее Θ(n**(1/k)) путем индукции из доказательства k = 2.

Точное решение

Мы выводим рекурсию, оптимизируя, где нужно отбросить первое яйцо (этаж g), предполагая, что мы знаем оптимальные решения для меньших параметров. Если яйцо разбивается, у нас есть г-1 этажа ниже, чтобы исследовать яйца k-1. Если яйцо сохранится, у нас есть n-г этажи, чтобы исследовать с помощью k яиц. Дьявол выбирает худшее для нас. Таким образом, при k > 1 рекурсия

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

Ответ 5

Разве это не предполагает, что вы используете "тот же кот"?

Вы можете подойти к нему математически, но что хорошая вещь о математике... с правильными предположениями, 0 может равняться 1 (при больших значениях 0).

С практической точки зрения вы можете получить "похожих кошек", но вы не можете получить "тот же кот".

Вы можете попытаться определить ответ эмпирически, но я думаю, что будет достаточно статистических различий, что ответ будет статистически бессмысленным.

Вы можете попробовать использовать "Тот же кот", но это не сработает, так как после первой капли это уже не тот же кот. (Точно так же onecan никогда не ступает в одну и ту же реку дважды)

Или вы можете агрегировать здоровье кошки, отбирать пробку с очень близкими интервалами и находить высоты, для которых кошка "в основном живая" (против "в основном мертвых" от "Принцесса-невеста" ). Кошки выживут в среднем (до последнего интервала).

Я думаю, что я отклонился от первоначального намерения, но если вы идете по эмпирическому маршруту, я голосую за то, что вы начинаете как можно выше и продолжаете бросать кошек по мере того, как высота уменьшается, пока они не выживут. А затем повторите проверку выживших кошек.

Ответ 6

Я принял несколько иной метод для создания решения.

Я начал с разработки максимального пола, который можно было бы покрыть с помощью x cats и y guesses, используя следующий метод.

Начните с 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 следуют за combination кусочный шаблон.

Для 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).

Ответ 7

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). 

Ответ 8

Я не могу читать google blogspot на этом (благодаря работам blogwall), но я не думаю, что лучший поиск в двоичном стиле был бы лучшим. Причина состоит в том, что двоичный поиск основан на понятии, что ответ, который вы ищете, имеет равные шансы быть в любом индексном индексе в списке. Однако в этом случае это неверно. В этом случае ответ будет иметь более высокую вероятность быть ближе к одному концу диапазона, чем к другому. Я не знаю, как это повлиять на поиск, но это интересная мысль.

Ответ 9

все эти сумасшедшие разговоры о кошках.. и это просто догадка номер проблемы с минимальными догадками (количество кошек). не должно быть необходимости искусственно (и некорректно) определять бесконечность как часть решения. переменная должна была быть названа верхней или максимальной попыткой или некоторой такой. определение проблемы (вещь кошки) имеет некоторые серьезные проблемы, хотя люди с ответом на потенциал жестокости животных, а также множество аспектов такой проблемы, возникающей в реальной жизни, например. воздушное сопротивление, гравитация - это ускорение и другие подобные параметры реальной жизни проблемы. так что, возможно, это нужно было спросить совершенно по-другому.