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

Автор NALP, 14 лет назад, По-русски

Задача А (Div-2). Игрушечные армии

Утверждение первое: пусть пусть первым ходом было убито x солдат, а вторым y, тогда третьим ходом количество убитых будет равно min(n - x, n - y) = n - max(x, y). Значит, общее количество убитых будет равно x + y + n - max(x, y) = n + min(x, y), и именно эту величину нам нужно максимизировать. Рассмотрим ограничения на эти переменные: 0 ≤ x ≤ n, 0 ≤ y ≤ n - x. Значит, нам нужно найти максимум функции f(x, y) = n + min(x, y) в этой области. Понятно, что если мы скажем, что y = n - x (то есть для y примем крайнее положение), то ответ не уменьшится, а значит, можем свести нашу функцию к f(x) = n + min(x, n - x) на отрезке [0, n]. Очевидно, максимум этой функции равен n / 2 в точке x = n / 2.
Ответ: n / 2.

Задача E (Div-1). Две последовательности

Для начала, попробуем нашу задачу решить, не задумываясь об асимптотике. Рассмотрим динамическое программирование, где состояние - это пара (i, j) (а значение - это минимальная суммарная длина двух последовательностей), которое означает, что первая последовательность у нас заканчивается строкой i, а вторая - строкой j. Переходы тогда выглядят следующим образом: мы должны взять элемент с номером v = max(i, j) + 1 и добавить в одну из последовательностей, таким образом перейти в новые состояния (i, v) и (v, j), пересчитав нужным образом значение.

Выпишем более формально, но теперь использовав динамическое программирование "назад", считая, что i > j:


Теперь придумаем окончательное решение. В силу постановки нашей задачи, можно задачу свести к другой динамике - D(i, s), где состояние означает, что одна из последовательностей заканчивается на строку номер i, а вторая - на саму строку s, причем, заметим, что под строкой s будем подразумевать не только строки из входных данных, но и все их суффиксы длиной от 0 до l. Вспомним, что строки у нас бинарные длиной не более 20 символов, а это значит, что строки можно закодировать двоичными числами, в этом случае строка кодируется парой - длиной и самим числом (это строка, если ее интерпретировать как двоичную запись; эта тонкость нужна, т.к. в строках, возможно, присутствуют лидирующие нули, в этом случае разные строки будут переводится в одно и то же число), причем, общее количество пар будет не более 221.

Будем итерироваться по i и поддерживать наш массив со значениями динамики (одномерный, размером 2l). При переходе, нам нужно обновить его в соответствии с формулами выше: по первой нам нужно ко всем элементам массива прибавить величину f(i - 1, i) - это можно сделать, поддерживая дополнительную переменную balance и прибавлять к ней (таким образом, реальное значение элемента i будет равно balance + d[i], хотя в самом массиве значение хранится будет d[i]). А второе обновление еще проще, мы должны перебрать какой длины у нас будет наложение строки на последовательность, взять соотвествующее значение в массиве, и по всем таким перебираемым величинам взять минимум и записать его в соответствующее место в массиве.

Реализовать этот алгоритм можно за асимптотику O(n * l) с требуемой памятью O(n + 2l).
  • Проголосовать: нравится
  • +13
  • Проголосовать: не нравится

14 лет назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится
Было бы здорово, если бы Вы хотя бы обяснили значения всех функций, которые вы вводите (к примеру, f). Не смотря на то, что это может казаться более-менее понятным, задачу пока сдало не много человек, а разборы не кажутся столь уж простыми.
  • 14 лет назад, # ^ |
      Проголосовать: нравится +11 Проголосовать: не нравится
    функция f была определена в самом условии задачи, а все остальные обозначения я объяснял по ходу... правда, разбор и правда получился несколько сложным и туманным. пожалуй, я его попробую немного переписать
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
При этом стоит учесть, что формула d(i, j) = d(i - 1, j) + f(i - 1, i), если я всё правильно понял, неверна: строчка i может пересекаться и с (i-2)-й и так далее. Наверное, стоит сразу говорить про s.
14 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

в первом случае i - 1 != j, а это значит, i-ая строчка обязательно в одной последовательности c i-1, поэтому формула верна
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Я не об этом. Пусть n = 5, a[i] = "0". Тогда f(i, j) = 1, d(i, 0) = 1.
    Но d(5, 0) = d(3, 0) + f(3, 4) + f(4, 5) >= 2.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      ок, я понял твой вопрос. действительно, i-ая может пересекать i-2-ую и далее... но т.к. все строки имеют одинаковую длину, то одна строка не может быть подстрокой другой (случай, когда строки равны неинтересен), а это значит, что можно говорить, что первая строка в последовательности добавляет в ответ l, а каждая последующая - l - f(i, j), то есть по сути нам нужно минимизировать "дополнительные символы"
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Это был не вопрос ) Раз ты хотел немного переписать текст, я решил обратить твоё внимание на эту неточность.