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

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

Итак, есть узлы: N = {1,...,n}

Есть списки узлов (пути), без повторяющихся элементов (циклов):

S1 = {1,2,3...}
S2 = {3,1,2...}
...

Каждый путь имеет некий вес, пусть i-тый путь имеет вес w[i].

Пути пересекаются, если имеют хотя бы один общий элемент.
Требуется найти не пересекающиеся пути так, чтобы сумма весов решения была максимальной.

Ограничения:

25 узлов, 50 000 путей


Подскажите, в какую сторону копать?

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

13 лет назад, # |
  Проголосовать: нравится -30 Проголосовать: не нравится

  • 13 лет назад, # ^ |
      Проголосовать: нравится +6 Проголосовать: не нравится
    Из ребуса понял только то, что копать надо вниз :)
    Али это намек на динамическое программирование?
  • 13 лет назад, # ^ |
      Проголосовать: нравится +1 Проголосовать: не нравится
    На этот трек еще надо денег насобирать.
    • 13 лет назад, # ^ |
        Проголосовать: нравится +5 Проголосовать: не нравится
      Подозреваю, что anonymous имел в виду использовать деньги, оставшиеся после продажи компьютера.
  • 13 лет назад, # ^ |
      Проголосовать: нравится +12 Проголосовать: не нравится
    оффтоп: вроде как просили большие картинки не публиковать?!
    • 13 лет назад, # ^ |
        Проголосовать: нравится +13 Проголосовать: не нравится
      Просили позднее, и, видимо, в именно связи с этой картинкой :)
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Какие ограничения?
  • 13 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    Допустим, 25 узлов и 1000 путей.
    Upd: а давай много путей будет - этак 50 тыс.
    • 13 лет назад, # ^ |
        Проголосовать: нравится +1 Проголосовать: не нравится

      Можете описать задачу адекватнее, чем как огурцы ложкой банка майонеза?

      Пока это выглядит как "Дано N множеств. Выберите из них наибольшее количество попарно не пересекающихся, с весами". В этой задаче надо копать к велосипеду, ибо без весов NPC

      • 13 лет назад, # ^ |
          Проголосовать: нравится +14 Проголосовать: не нравится
        Еще бы кое-кто выражался более адекватно, чем лопата стрелка вниз велосипед)
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Тогда можно обычным перебором.
      Нужно перебрать все различные пары путей, и на каждой итерации проверять пересекаются они или нет, если нет то запоминаем вес. Среди всех весов которые запомнили выбираем максимальный.
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        *два пути пересекаются если они имеют хотя одну общую вершину, тут значит надо просто проверить есть ли в двух наборах одинаковые элементы.
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Спасибо за идею. Посмотрим, подскажет ли комьюнити что-либо изящнее брутфорса.
        • 13 лет назад, # ^ |
          Rev. 4   Проголосовать: нравится 0 Проголосовать: не нравится

          Если путей много, тогда надо все множества путей разбить на не пересекающееся подмножества (путей), отсортировать по весу (внутри подмножества) и выбрать самые тяжелые.
        • 13 лет назад, # ^ |
          Rev. 2   Проголосовать: нравится +4 Проголосовать: не нравится

          > Спасибо за идею. Посмотрим, подскажет ли комьюнити что-либо изящнее брутфорса.

          И получит 1млн долларов от математического института Клэя за решение проблемы Кука. 

          • 13 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится
            Для рюкзака же есть техника решения.
            • 13 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              Для рюкзака с целыми весами.
              • 13 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится
                Если смотреть из чисто практической точки зрения, то важнее даже не то что они целые, а то что они небольшие.

                В компьютере все равно нельзя иррациональное число представить, а рациональные можно привести к общему знаменателю. Правда тогда числа будут хоть и целыми, но очень большими.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Лучше это не только в комментариях писать, а и в основном посте менять. А то человек прочитав пост видит неадекватно сформулированное условие без ограничений и дальше топик не читает.
13 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

перепост


13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Если узлов <= 25, то можно каждый путь хранить битовой маской. Их всего 225 ~ 32*106. Следовательно, для каждой маски можно посчитать d1[mask] := max {вес пути среди всех путей, маска которых есть подмаска mask (т.е. mask1 OR mask = mask)), а также d2[mask] := max {вес пути среди всех путей, маска которых не пересекается с mask (т.е. mask1 AND mask = 0)) Имея эти динамки, имеем ответ:
ans = максимуму по всем маскам (d1[mask] + d2[mask]). В 256 мегабайт решение должно уложиться. Со временем хуже - n*2n. Скорее всего, это не влезет в ТЛ (если это надо скармливать тестеру), но покопать, думаю, можно)))

  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    это работает для двух путей. Для большего количества, видимо, можно копать в этом же направлении...
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Тут такое дело.. Путь это список, то есть нам важна последовательность.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      ааа какая разница? К их пересечению/непересечению порядок отношения не имеет...
  • 13 лет назад, # ^ |
      Проголосовать: нравится +5 Проголосовать: не нравится
    Вы, наверное, имели ввиду m * 2n(где n - количество узлов, а m - количество путей). 

    Если так и, если я, конечно, нигде не ошибаюсь, то с такой же асимптотикой можно решить эту задачу восходящей динамикой. Для каждой маски от 0 до 2n (это mask1) переберём все маски путей (mask2, m штук) и будем делать переход на d[mask1 or mask2] возможным, только если mask1 and mask2 = 0. На каждой такой итерации d[mask1 or mask2] = max (d[mask1 or mask2], d[mask1] + w[mask2]). 

    Это можно делать по след. причинам: 
    1) предыдущие пути не должны пересекаться с новым путём и, если mask1 and mask2 = 0, то мы ещё не брали mask2.
    2) В результате такой процедуры будут браться только непересекающиеся пути и совокупности путей.
    3) Если мы дошли до какой-то маски, то ранее уже рассмотрели все нужные её разрешённые подмаски.

    Прошу поправить, если где-то ошибся.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Я имел ввиду n* 2n, ибо получать каждое новое значение можно получать из предыдущих за n действий
      (d[mask] = max(w(mask) (вес пути, дающей эту маску),  max d[mask AND(
      2n - 1 - (1 << i))] по всем i от 0 до n-1)).

      Ваше решение верно, но m * 2n имеет ТЛ при m ~ 105...
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        =================================
        Ну да, это я понимаю (про асимптотику и время).

        А не могли бы вы поподробнее объяснить переходы для d1 и d2 (в частности, переход из последнего вашего сообщения)? Я вижу, что там вы перебираете все подмаски, отличающиеся на один бит от текущей, но есть же ещё (могут быть) подмаски , отличающиеся на более, чем один бит. 

        Этот момент, к сожалению, мне не совсем ясен.
        • 13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Конечно, могут быть, но все они учтены в d1[подмасок]. (т.к. если подмаска отличается на 2+ бита от текущей, то она является подмаской
          какой-то подмаски, отличающейся от текущей на один бит)
13 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

Вообще, раз дискуссия еще жива.

1) Строим граф совместимости. Пересекаем хоть bitset-ом.
2) Это задача о максимальной клике (пусть с весами). Она решается за 2n / 2, n - число вершин.