Каков алгоритм решения этой проблемы?

#python #algorithm

#python #алгоритм

Вопрос:

У нас есть ряд из X гнезд, и у нас есть Y птиц. У каждой птицы есть гнездо. Птицы не любят друг друга и хотят сидеть в своих гнездах как можно дальше от других птиц и в концах ряда, насколько это возможно. Поскольку птица сидит в гнезде, она больше не двигается. Птицы прилетают к гнездам одна за другой. Нужно найти, сколько свободных гнезд справа и слева от последней птицы.

Например, если у нас есть 10 гнезд и 1 птица: Ответ: (4, 5) 10 гнезд и 2 птицы: (1, 3) 10 гнезд и 3 птицы: (2, 1) и т.д. Количество гнезд может составлять около 5 000 000 000.

Моя попытка:

 def rec(x, y):
y -= 1
z = x // 2
print('y =', y)
if y == 0:
    if z % 2 == 0:
        return x - z - 1, x - z
    elif z % 2 != 0:
        return x-z, x-z
if z == 4:
    return 1, 2
elif z == 3:
    return 1, 1
else:
    return rec(z, y)
  

Но я не могу учесть тот факт, что, например, если гнезд 17, то третья птица будет сидеть на гнезде справа от первой, а не между первой и второй.

Комментарии:

1. Я думаю, что меня могут немного смутить параметры алгоритма. Извините, но я не понимаю, как, если есть 10 гнезд и только одна птица, как мы узнаем, где эта единственная птица выберет. Например, (9,0) может быть возможным, или это должно быть (4,5)?

2. «Птицы не любят друг друга и хотят сидеть в своих гнездах как можно дальше от других птиц и на концах ряда» — это означает, что птица каждый раз будет выбирать середину свободного гнезда. Если 10 гнезд свободны, мы будем считать это как 4 слева и 5 справа.

3. @OstenGibson, (9,0) не сработает, потому что птицам также не нравятся концы строки, но это может быть так же легко (5,4), как (4,5), кажется, есть какое-то правило для разрыва связей, которое было исключено из описания. И (1,3) для сценария с 2 птицами не имеет смысла, предположительно, вторая птица отправится в середину цикла из 5 гнезд, получив ответ (2,2).

4. @jasonharper, я полагаю, что не имеет значения, будет ли это (5,4) или (4,5) изначально, потому что ответ будет таким же (по-видимому).

5. Ах, извините, да, формулировка меня немного смутила. ands сокрушили мой мозг. И да, как @jasonharper, сценарий с двумя птицами также своеобразен.

Ответ №1:

Как указал @jasonharper, утверждение для сценария 2 bird неверно (с использованием общей логики). Если цель — это то, что вы описали, то решение представлено ниже:

 nests = 17
birds = 3

free = [(1, nests)]
for b in range(birds):
  t = max(free, key = lambda p: abs(p[1] - p[0]))
  break_point = (t[0] t[1])//2
  free.remove(t)
  free.append((t[0], break_point-1))
  free.append((break_point 1, t[1]))

left, right = free[-2], free[-1]
answer = (left[1]-left[0] 1, right[1]-right[0] 1)
print(answer)
  

Объяснение

В списке free хранятся кортежи, обозначающие разные диапазоны (начиная с 1) пустых гнезд (это объединение диапазонов пустых гнезд).

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

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