Izot_NNSTU's blog

By Izot_NNSTU, 9 years ago, In Russian

Столкнулся с задачкой, которую легко переформулировать в терминах олимпиадного программирования. Уверен, такое решалось 100000 раз, но я что-то не придумал быстро элегантного решения (теряются навыки ACM) :)

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

Формально так: есть n целых чисел (балансы друзей), сумма этих чисел равна 0. За ход можно взять пару чисел и прибавить произвольное целое число к первому числу этой пары, при этом отняв от второго.

n1, n2 -> n1'=n1+k, n2'=n2-k

Задача — за наименьшее число ходов превратить все числа в 0.

Не смог убедить себя, что жадный алгоритм работает :)

Единственное, что придумал — пролить макспоток минимальной стоимости через граф с истоком, стоком, слоем должников и слоем кредиторов, где каждый должник соединен с каждым кредитором ребром с пропускной способностью бесконечность. При этом функция стоимости будет странная — 1 если по ребру течет какой-то поток и 0 в противном случае. Вообще не уверен, что алгоритм нахождения потока будет работать с такой функцией.

Короче говоря, я уверен, что это какая-то стандартная задача. Кто напомнит как такое решать?

Кстати, задача становится немного интереснее, если добавить ограничение на номинал купюр, которые есть у друзей.

  • Vote: I like it
  • +8
  • Vote: I do not like it