Коллективно оплатить счет проблемы

23

За столом человек. й человек должен платить долларов.nipi

Некоторые люди не имеют правильных счетов для оплаты точно , поэтому они придумали следующий алгоритм.pi

Во-первых, каждый кладет часть своих денег на стол. Затем каждый человек забирает деньги, которые он переплатил.

Счета имеют фиксированный набор номиналов (не является частью ввода).

Пример: предположим, что есть два человека, Алиса и Боб. Алиса должна 5 долларов и имеет пять долларовых купюр. Боб должен 2 доллара и имеет один счет на 5 долларов . После того, как Алиса и Боб положили все свои деньги на стол, Боб забирает 3 доллара , и все счастливы.

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

Я хочу найти алгоритм со следующими свойствами:

  1. Во входных данных указывается количество людей, сколько каждый человек должен и сколько счетов каждой деноминации имеет каждый человек.

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

  3. Алгоритм сообщает каждому человеку, какие счета убрать со стола во втором раунде.

  4. Количество купюр, положенных на стол + количество купюр, снятых со стола, сведено к минимуму.

Если выполнимого решения не существует, алгоритм просто возвращает ошибку.

Чао Сюй
источник
9
Являются номиналов банкнот фиксированной заранее (скажем , к американскому номиналов $ 1, $ 2, $ 5, $ 10, $ 20, $ 50 и $ 100), или часть входного? Другими словами, это алгоритм должен обработать возможность , что Мефистофель имеет три $ 7 законопроектов, в $ счет 13, и пятнадцать $ 4 счета ?
Джефф
1
Счета фиксированы. Я думаю, в этом случае я не могу уменьшить сумму подмножества и доказать, что это NP-Hard. Я отредактирую это.
Чао Сюй
1
Вам нужен способ выразить 4/5 как одну оптимизацию. Невозможно оптимизировать для этих двух независимых условий. Я знаю о том, что вы намерены, у меня раньше была похожая проблема, но вам нужно точно определить, что значит оптимизировать для обоих условий.
edA-qa mort-ora-y
3
Я думаю, что было бы лучше, в качестве отправной точки, предположить, что либо все оплачивают счет точно, либо алгоритм просто сообщает об ошибке.
Джефф
2
Какой именно вопрос здесь, есть ли требования к сложности? Написание наивного алгоритма кажется тривиальным, или я что-то упустил?
Стефан Гименес

Ответы:

6

Если вы переформулируете проблему немного другим (но эквивалентным) способом, алгоритм становится более очевидным:

В нем участвует сторон:n человек и один ресторан. Пусть p i будет суммой денег, которую я должен иметьпосле того,как еда закончена и оплачена. Например, если Алиса$36 и задолжал$25, Боб имеет$12 и должен$11, и Карл имеет$30 и задолжал$25, мы говоримчто р 0 есть ресторан и есть:n1piip0

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=[0000000000000011111111110000111111111100]

указывает, что Алиса начала с $ 1, $ 5, $ 10, $ 20, Боб начал с $ 1, $ 1, $ 5, $ 5, а Карл начал с $ 10 и $ 20.

Опять же, цель состоит в том, чтобы минимизировать количество счетов, которые переходят из рук в руки. Другими словами:

Minimize:i=0n1j=0m1Ci,jxi,jsubject to:i=0n1xi,j=1 for 0j<m,j=0m1xi,jbj=pi for 0i<n,andxi,j0

Первое ограничение говорит о том, что решение может назначить определенный счет только одной стороне, а второе гарантирует, что каждый платит соответствующую сумму.

Это задача 0,1 INTEGER PROGRAMMING и является NP-полной (см. [ Karp 1972 ]). Страница Википедии о линейном программировании содержит информацию о различных алгоритмах, которые можно использовать для решения подобных задач.

Есть потенциально несколько оптимальных решений; вручную первое решение для примера, который я придумал, было:

x=[0101100111101000000000001000000000001000]

что означает Алиса платит ровно $ 5 и $ 20, Боб платит ровно $ 1, $ 5 и $ 5, и Карл переплачивает $ 10 и $ 20 , а затем удаляет $ 5 из таблицы.

Я также использовал модуль Mixed Integer Linear Program системы Sage Math , который имеет возможность использовать различные решающие механизмы ( GLPK , COIN , CPLEX или Gurobi ). Первое решение, которое он дал, было

x=[0101010111101000000000001000000000000100]

это почти то же самое, за исключением того, что Карл взял «другие» 5 долларов, которые Боб положил на стол.

Cx

Определите подмножество людей, которые могут заплатить уменьшенную сумму? Или, возможно, подмножество людей, которые все еще могут оплатить весь счет, то есть они платят за своего друга.

Ваше окончательное утверждение создает впечатление, что вы заинтересованы в том, чтобы номиналы счетов были фиксированными, однако это не меняет проблему.

O(1)

Дэвид
источник
Что эта проблема может быть выражена как IP было (почти?) Ясно; но насколько хорошо это решение? Можно ли эффективно решить IP-адреса созданной формы? Если нет, есть ли более быстрый алгоритм?
Рафаэль
Существует более сжатая форма этого IP, имеющая переменную для числа банкнот определенного номинала, чем переменная 0,1. Фиксированные деноминации немного меняют сложность, если число людей также фиксировано, алгоритм Ленстры может решить ее за полиномиальное время.
Чао Сюй
-2

Конечно, некоторые основные начинания могут включать в себя наименьшие доступные счета для достижения общей суммы общего счета. Если вы не хотите допускать счета на 2 доллара , каждый может просто удалить самый большой счет, который он может взять из пула, и получит его относительно быстро. $ Банкнота 2 броска , что от , как это не подразделять хорошо в к другим конфессиям и значительно усложняет задачу. Также существует ряд других оптимизаций, которые можно было бы сделать, чтобы сделать наблюдения о необходимости добавления дополнительных средств в течение первого раунда (например, если общее количество счетов в 1 доллар всегда достаточно для покрытия счета, то каждый может прекратить вносить, если они еще не вложили достаточно для их счета).

Эй Джей Хендерсон
источник