Як вирішується проблема з вибором піци за допомогою методів динамічного програмування?


9

Проблема з вибором піци Вінклера:

  • Круглий пиріг для піци з nшматочків, де шматочок iмає площу, S_iтобто площа для кожного шматка пирога.
  • Пожирачі Еліс та Боб по черзі збирають скибочки, але грубо створювати кілька прогалин у пирізі (вважайте, що це не дозволяється).
    • Таким чином, кожен їдець має обмеження приймати один з двох скибочок, прилеглих до відкритої області. Аліса йде першою, і обидва їдці шукають якомога більше пирога.

Як би алгоритм динамічного програмування визначав, скільки їсть пиріг Аліса, якщо і Аліса, і Боб грають ідеально, щоб максимально споживати свою піцу?

Моє розуміння:

У загальній проблемі з DP ми продовжуємо пошук підзадач, які можна візуалізувати за допомогою дерева рекурсії або, більш чітко, за допомогою DAG. Тут я не знаходжу жодного приводу, щоб знайти підпроблеми тут.

Тут, для заданого набору S_i s, нам потрібно збільшити площу скибочок, з'їдених Алісою. Це залежатиме від вибору перестановки шматочків піци з (n-1) перестановок. Вибираючи зріз максимальної площі з двох варіантів, доступних у кожні n \ 2 витків, які отримує Аліса, ми отримаємо загальну площу зрізу для перестановки. Нам потрібно знайти область зрізу для всіх таких перестановок. І тоді максимум із них.

Хтось може мені допомогти, як рухатись вперед?

Відповіді:


5

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

  1. Якщо піци немає, результат - 0
  2. Якщо є лише один фрагмент, це такий фрагмент
  3. Якщо є хоча б два скибочки, то результат такий:

(використовуючи синтаксис Python)

max(slices[0] + sum(slices[1:]) - pizzaAmount(slices[1:]),
    slices[-1] + sum(slices[:-1]) - pizzaAmount(slices[:-1]))

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

Ви можете реалізувати це за допомогою DP (або запам'ятовування), оскільки масив дійсно виправлений, і ви можете просто розглянути як параметри перший і останній індекс фрагмента.

Щоб вирішити оригінальну повну проблему, вам просто потрібно спробувати всі фрагменти як початковий фрагмент і вибрати той, який максимально забезпечує результат.


Дякую «6502». Я можу краще уявити проблему, скориставшись підказкою "розглянути скибочки, щойно розміщені на ряду, і вибрати один з двох кінців". Враховуючи рецидиви, це також турбота про оптимальний вибір опонента. Я скоро опублікую офіційний алгоритм. Дякую, хлопці!!

Просто цікаво, який порядок складності для цього алгоритму? 0 (n * 2 ^ n)?

@Akron: Це було б без динамічного підходу до програмування чи запам'ятовування. Однак ви можете скористатись тим, що результат дії pizzaAmountзалежить тільки від того, які показники старту та зупинки залишилися скибочки, а не від послідовності, яку шматочки піци ви з'їли, ви та ваш друг вже їли, щоб ви могли зберігати результат у матриця, щоб уникнути перерахунку. Таким чином, порядок роботи алгоритму є O (n ** 2).
6502

Якщо хтось все ще намагається зрозуміти, це посилання має дуже приємне пояснення.
Аміт Шехар

3

Для частини піци визначте F(i,j)як максимум, скільки може з'їсти людина, яка першою вибирає шматочок. Шматочки частини піци (i,j):

if i <= j than slices i, i+1, ..., j-1, j
if i > j than slices i, i+1, ..., n-1, n, 1, 2, ..., j-1, j
and we don't define it for whole pizza, abs(i-j) < n-1

Визначте R(i,j)(скільки залишилось для другої людини) як sum(S_x, x in slices(i,j)) - F(i,j).

З:

F(i,i) = S_i,
F(i,j) = max( S_i + R(i+1,j), S_j + R(i,j-1) ),

максимум, що Аліса може з'їсти, обчислюється:

max( S_i + F(i+1, (i-1) if i > 1 else n) ).
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.