如果以稍微不同(但等效)的方式重述该问题,则算法将变得更加明显:
有参与方:个人和一个餐厅。令为在饭食完结并支付后应该拥有的金额。例如,如果爱丽丝(Alice)有36 美元并欠25 美元,鲍勃(Bob)有12 美元并欠11 美元,卡尔(Carl)有30 美元并欠25 美元,我们说是餐厅,并且有:nn−1piip0
p=(61,11,1,5)
就是说,当饭食在餐厅时应为 61 美元,爱丽丝应为 11 美元,鲍勃应为 1 美元,卡尔应为 5 美元。
现在,让列举所有涉及的账单。例如:bm
b=(1,5,10,20,1,1,5,5,10,20)
钞票的面额无关紧要,但是在此示例中,我选择了纸币的美元面额,因为它们很熟悉。
我们正在设法减少易手票据的数量,因此我们使用矩阵将“成本”与离开票据的人相关联。该矩阵中的0项指示每个方以哪个帐单开头(对于所有,因为餐厅以无帐单开头)。ij{0,1}CC0,j=0j
继续我们的示例:
C=⎡⎣⎢⎢⎢0011001100110011010101010101010101100110⎤⎦⎥⎥⎥
表示Alice以$ 1,$ 5,$ 10,$ 20开始,Bob以$ 1,$ 1,$ 5,$ 5开始,而Carl以$ 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整数编程问题,并且是NP完全的(请参阅[ Karp 1972 ])。有关线性编程的Wikipedia页面包含有关可用于这些类型问题的不同算法的信息。
可能有多个最佳解决方案。手工解决这个例子的第一个方法是:
x=⎡⎣⎢⎢⎢0100100001001000101000000001100010001000⎤⎦⎥⎥⎥
这意味着爱丽丝恰好支付$ 5和$ 20中,鲍勃恰好支付$ 1 $ 5和$ 5,和卡尔支付高价$ 10和$ 20,然后删除一个$从表5。
我还使用了Sage Math系统的Mixed Integer Linear Program模块,该模块具有使用不同求解器后端(GLPK,COIN,CPLEX或Gurobi)的能力。它给出的第一个解决方案是
x=⎡⎣⎢⎢⎢0100100001001000001010000000100110001000⎤⎦⎥⎥⎥
这几乎是一样的,除了卡尔拿走了鲍勃在桌上的“其他” 5美元。
以这种方式解决问题可以满足您列出的所有属性(您可以从和解决方案矩阵推断出哪些票据最终会出现在哪里)。也许是#4例外,该问题的评论中对此进行了讨论。我不清楚在线性方程组没有可行解的情况下您要做什么:XCx
确定可以支付减少的总额的一部分人?也许还有一部分人仍然可以支付全部账单,即他们为朋友付款。
您的最终声明使您似乎对票据面额固定的情况感兴趣,但这并不会改变问题。
无论如何,还有一种解决方案,其中每个人都使用信用卡付款。O(1)