Блог пользователя MrOnlineCoder

Автор MrOnlineCoder, история, 5 лет назад, По-русски

Всем привет. Прошу совет относительно динамического программирования. Прочитал уже достаточно теории о том, что это и возможные примеры. Однако, как приступаю к практике, а именно фильтрую архив задач по тегу ДП, начинаю пробовать решить какую-то задачу — ступор. Смотрю разбор, и возникают два вопроса:

  1. Как определить, что будет означать $$$dp_{ij}$$$ для определенных $$$i, j$$$ в контексте данной задачи? (т.е. грубо говоря, что именно мы будем хранить в массиве дп)

  2. Как определить эти "волшебные" формулы переходов?

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

Заранее спасибо.

  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

»
5 лет назад, # |
  Проголосовать: нравится +18 Проголосовать: не нравится

Расскажу, как у меня это происходило на примере задачи. 1316E - Выбор команды

  1. Так, в задаче надо посчитать какую-то непонятную фигню, при этом, наверное, я смогу добавить человека и ее пересчитать. Наверное, задача на динамику.

  2. Ага, $$$p \leq 7$$$. Возможно, в этой динамике одним из параметров будет маска членов команды.

  3. Теперь нужно как-то ограничить рассмотренных людей. Ну тут работает стандартный способ — перебирать последнего рассмотренного.

  4. Круто! $$$dp_{i, mask}$$$ — рассмотрели первые $$$i$$$ людей, при этом в команду набрали людей на позиции, отмеченные в $$$mask$$$.

  5. Ой, там еще болельщики есть. Надо с ними тоже что-то делать. МБ засунуть количество взятых болельщиков в состояние? Нет, много получится, надо что-то другое.

  6. О, если зафиксирована команда, то болельщиков можно просто жадно набирать! Давайте тогда просто будем перебирать людей в порядке убывания их веса как болельщика, и давать возможность стать болельщиком, если команда болельщиков пока слишком маленькая. Вроде как норм план.

  7. Теперь нужны формулы. Ну тут мы очевидно перебираем все маски и последнего человека. У него есть три возможности:

  • Никуда не войти. $$$dp_{i, mask} = dp_{i - 1, mask}$$$
  • Попасть болельщиком, если они еще не заполнились. $$$dp_{i, mask}$$$ $$$max= dp_{i - 1, mask} + a_i$$$.
  • Стать членом команды. Перебираем его позицию в команде, $$$dp_{i, mask}$$$ $$$max= dp_{i - 1, mask \oplus (1 « j)} + c_{i, j}$$$.
  1. Ну вроде как формула рабочая, го писать.

В простых задачах на динамику отсутствуют пункты 5-6, поэтому эта задача и стала div2E. Да и в целом задачи на динамику на масках считаются сложными, я просто привел пример того, как я придумываю динамику в задачах.

Общие советы — чтобы придумать состояние, можно смотреть, что именно тебе нужно в задаче, каких параметров не хватает, чтобы ее посчитать. Иногда ограничения задачи могут в этом помочь.

Чтобы придумать формулы достаточно посмотреть, откуда ты можешь прийти в твое состояние — либо рассмотрев возможности последнего человека, хода и так далее. Т.е. рассматриваешь самый крайний случай, и формула получается!

  • »
    »
    5 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

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