Если вы переформулируете проблему немного другим (но эквивалентным) способом, алгоритм становится более очевидным:
В нем участвует сторон:n человек и один ресторан. Пусть p i будет суммой денег, которую я должен иметьпосле того,как еда закончена и оплачена. Например, если Алиса$36 и задолжал$25, Боб имеет$12 и должен$11, и Карл имеет$30 и задолжал$25, мы говоримчто р 0 есть ресторан и есть:n−1piip0
p=(61,11,1,5)
То есть, когда еда заканчивается, в ресторане должно быть 61 доллар , у Алисы должно быть 11 долларов , у Боба - 1 доллар, у Карла - 5 долларов .
bm
b=(1,5,10,20,1,1,5,5,10,20)
Деноминации векселей не имеют значения, но я выбрал деноминации бумажной американской валюты для этого примера, потому что они знакомы.
ij{0,1}CC0,j=0j
Продолжая наш пример:
C=⎡⎣⎢⎢⎢0011001100110011010101010101010101100110⎤⎦⎥⎥⎥
указывает, что Алиса начала с $ 1, $ 5, $ 10, $ 20, Боб начал с $ 1, $ 1, $ 5, $ 5, а Карл начал с $ 10 и $ 20.
Опять же, цель состоит в том, чтобы минимизировать количество счетов, которые переходят из рук в руки. Другими словами:
Minimize:subject to:and∑i=0n−1∑j=0m−1Ci,jxi,j∑i=0n−1xi,j=1 for 0≤j<m,∑j=0m−1xi,jbj=pi for 0≤i<n,xi,j≥0
Первое ограничение говорит о том, что решение может назначить определенный счет только одной стороне, а второе гарантирует, что каждый платит соответствующую сумму.
Это задача 0,1 INTEGER PROGRAMMING и является NP-полной (см. [ Karp 1972 ]). Страница Википедии о линейном программировании содержит информацию о различных алгоритмах, которые можно использовать для решения подобных задач.
Есть потенциально несколько оптимальных решений; вручную первое решение для примера, который я придумал, было:
x=⎡⎣⎢⎢⎢0100100001001000101000000001100010001000⎤⎦⎥⎥⎥
что означает Алиса платит ровно $ 5 и $ 20, Боб платит ровно $ 1, $ 5 и $ 5, и Карл переплачивает $ 10 и $ 20 , а затем удаляет $ 5 из таблицы.
Я также использовал модуль Mixed Integer Linear Program системы Sage Math , который имеет возможность использовать различные решающие механизмы ( GLPK , COIN , CPLEX или Gurobi ). Первое решение, которое он дал, было
x=⎡⎣⎢⎢⎢0100100001001000001010000000100110001000⎤⎦⎥⎥⎥
это почти то же самое, за исключением того, что Карл взял «другие» 5 долларов, которые Боб положил на стол.
Cx
Определите подмножество людей, которые могут заплатить уменьшенную сумму? Или, возможно, подмножество людей, которые все еще могут оплатить весь счет, то есть они платят за своего друга.
Ваше окончательное утверждение создает впечатление, что вы заинтересованы в том, чтобы номиналы счетов были фиксированными, однако это не меняет проблему.
O(1)