有效共享费用后偿还债务:每人最多1笔交易

时间:2016-05-11 12:16:51

标签: algorithm

上下文

我正在创建一个简化人与人之间共享费用的计划。费用有:

  • 最初支付费用的付款人
  • 一些贡献者,他们将支付一部分费用(注意付款人也是贡献者)

捐款人必须为某项费用支付的股份不一定必须相等。经过一些任意数量的开支后,有些人会欠钱,而其他人欠钱。

问题

问题是找到一个让所有人解决债务的简单方法。我不想让一些人付钱给其他人,而有些人根本不需要支付任何人,我希望一个人最多只需付一个人。此外,我想尽量减少一个人收到的超出他或她实际欠款的金额。例如,如果你欠100美元,你真的不想收到2000美元,并且必须向其他人转发1900美元。

模型

每个人都有债务。债务是:

  • 如果该人欠钱,则为正面
  • 如果该人欠款,则为负面
  • 零,如果以上都不是

因此,该模型由一组数字组成,代表债务。

这是一种零和的情况:人们所欠的金额等于人们欠款的金额(没有贷款人就没有贷款)。这意味着无论谁收到付款,如果最后每个人都支付了欠款,就没有人欠任何钱。

Anne向Bob支付100美元。如果安妮有100的债务,她的债务现在为0.如果鲍勃的债务为-100,他的债务也是0.在该模型中,货币交易相当于从付款人的债务中扣除,并添加相同的债务相当于收件人的。

为了尽量减少交易中收款人的超额收款,我认为将最大的正债务加到每笔交易的最大负债中应该足够了。

实施

我正在考虑为负债使用最小堆,为正债使用最大堆。然后重复执行从最大最大到最小最小的事务。这可以通过将min的键增加最大值并删除max来完成。如果债务为零,则将其从堆中删除。

的伪代码

max成为maxHeap的最大元素,minminHeap的最小元素。 max.personmin.person分别是maxmin的债务人。

while(not done) do:
    new transaction.from(max.person).to(min.person)
    if(max + min = 0) then:               //remove both
        maxHeap.removeMax
        minHeap.removeMin
    else if (max + min < 0) then:         //keep in minHeap
        minHeap.increaseKey(min).by(max)
        maxHeap.removeMax
    else                                  //move min to maxHeap
        maxHeap.decreaseKey(max).by(|min|)

如果我没记错的话,这应该给我一个O(nlogn)的运行时间。

问题

我的推理是否正确?根据我的问题描述,我的解决方案会得到相当好的结果吗?有没有其他人有更快和/或更简单的解决方案,仍然坚持尽可能少收到多余资金的标准?

注意:如果重要,我将用Java实现它

编辑:我发现了另一个与此非常相似的问题:Algorithm to share/settle expenses among a group。但是,它并没有解决我的问题,因为我有每个人最多一笔交易的标准。

1 个答案:

答案 0 :(得分:2)

我已经编辑了答案,以满足一个收件人可以从多个人那里收到钱的情况,而不仅仅是来自一个人。见最下面。

有趣的问题 - 必须编码。这里是伪和数据,与Dyalog APL一样。

通常,确保最佳状态的唯一方法是使用蛮力。对于您的问题,当参与者人数约为12或更少时,这种方法很有效:

┌──┬──┬──┬──┬───┬───┬─────┬──────┬───────┬─────────┬──────────┬───────────┬─────────────┬──────────────┬─────────────────┐
│!1│!2│!3│!4│!5 │!6 │!7   │!8    │!9     │!10      │!11       │!12        │!13          │!14           │!15              │
├──┼──┼──┼──┼───┼───┼─────┼──────┼───────┼─────────┼──────────┼───────────┼─────────────┼──────────────┼─────────────────┤
│1 │2 │6 │24│120│720│5,040│40,320│362,880│3,628,800│39,916,800│479,001,600│6,227,020,800│87,178,291,200│1,307,674,368,000│
└──┴──┴──┴──┴───┴───┴─────┴──────┴───────┴─────────┴──────────┴───────────┴─────────────┴──────────────┴─────────────────┘

正如我们所见,数字因子迅速增加。如果10个参与者,它仍然是合理的360万,12个人已经是15亿。可能不值得考虑更多。

但是,如果我们谈论足够小的帮派,那么进行计算是相当微不足道的(除了一件事)。

您已设置此条件:

  

贡献者必须为某项费用支付的股票   不一定非得平等。

这并没有改变计算本身,但我不在这个答案如何股票结束之外。你必须有办法确定属于谁的东西。此处计算的基本要点是应付款的总和 付款 相等

考虑这个例子:

我们有4个人已经消耗了400美元。一个人支付了所有费用,他们决定平均分摊费用:

┌──────────┬───┬───┬───┬───┬─────┐
│Guy       │1  │2  │3  │4  │Total│
├──────────┼───┼───┼───┼───┼─────┤
│Should pay│100│100│100│100│400  │
├──────────┼───┼───┼───┼───┼─────┤
│Payed     │0  │0  │0  │400│400  │
└──────────┴───┴───┴───┴───┴─────┘

当1号球员支付0时,他显然需要额外支付100,等等。这是一个简单的案例。唯一的解决方案是:

    1 solutions with unique transfer sums. Best solution:
┌─────────────────────────┬──────┬──────┬──────┬──────┬─────┬────────┐
│Guy #                    │1     │2     │3     │4     │Total│Turnover│
├─────────────────────────┼──────┼──────┼──────┼──────┼─────┼────────┤
│Should pay               │100   │100   │100   │100   │400  │        │
├─────────────────────────┼──────┼──────┼──────┼──────┼─────┼────────┤
│Has paid                 │0     │0     │0     │400   │400  │        │
├─────────────────────────┼──────┼──────┼──────┼──────┼─────┼────────┤
│Gets from the one to left│0.00  │100.00│200.00│300.00│     │600     │
├─────────────────────────┼──────┼──────┼──────┼──────┼─────┼────────┤
│Pays to the one to right │100.00│200.00│300.00│0.00  │     │600     │
└─────────────────────────┴──────┴──────┴──────┴──────┴─────┴────────┘

请注意,表格包装 - 最左边和最右边是&#34;邻居&#34;。

我们看到每个差不多的人都会向表中的右邻居列付款,同样从他的左邻居那里得到一个。在添加他最初支付的费用,他现在得到的以及他现在支付的费用时,他最终会按照分配给他的正确总费用。

但是,如果#2支付100,而#4支付300:

┌──────────┬───┬───┬───┬───┬─────┐
│Guy       │1  │2  │3  │4  │Total│
├──────────┼───┼───┼───┼───┼─────┤
│Should pay│100│100│100│100│400  │
├──────────┼───┼───┼───┼───┼─────┤
│Payed     │0  │100│0  │300│400  │
└──────────┴───┴───┴───┴───┴─────┘

我们得到3个解决方案,低于最佳解决方案:

3 solutions with unique transfer sums. Best solution:
┌─────────────────────────┬──────┬──────┬──────┬────┬─────┬────────┐
│Guy #                    │1     │3     │4     │2   │Total│Turnover│
├─────────────────────────┼──────┼──────┼──────┼────┼─────┼────────┤
│Should pay               │100   │100   │100   │100 │400  │        │
├─────────────────────────┼──────┼──────┼──────┼────┼─────┼────────┤
│Has paid                 │0     │0     │300   │100 │400  │        │
├─────────────────────────┼──────┼──────┼──────┼────┼─────┼────────┤
│Gets from the one to left│0.00  │100.00│200.00│0.00│     │300     │
├─────────────────────────┼──────┼──────┼──────┼────┼─────┼────────┤
│Pays to the one to right │100.00│200.00│0.00  │0.00│     │300     │
└─────────────────────────┴──────┴──────┴──────┴────┴─────┴────────┘

最糟糕的一个:

Worst solution:
┌─────────────────────────┬──────┬──────┬──────┬──────┬─────┬────────┐
│Guy #                    │1     │2     │4     │3     │Total│Turnover│
├─────────────────────────┼──────┼──────┼──────┼──────┼─────┼────────┤
│Should pay               │100   │100   │100   │100   │400  │        │
├─────────────────────────┼──────┼──────┼──────┼──────┼─────┼────────┤
│Has paid                 │0     │100   │300   │0     │400  │        │
├─────────────────────────┼──────┼──────┼──────┼──────┼─────┼────────┤
│Gets from the one to left│100.00│200.00│200.00│0.00  │     │500     │
├─────────────────────────┼──────┼──────┼──────┼──────┼─────┼────────┤
│Pays to the one to right │200.00│200.00│0.00  │100.00│     │500     │
└─────────────────────────┴──────┴──────┴──────┴──────┴─────┴────────┘

上述情况更糟,因为结算付款时的总<营业额更大。你有这个标准:

  

我想尽量减少一个人收到的多余钱   超出他或她的实际欠款。

在大多数情况下这似乎是可能的,但我怀疑是否有任何保证。

现在考虑一下这种情况:

┌──────────┬──┬──┬──┬──┬──┬──┬──┬──┬─────┐
│Guy       │1 │2 │3 │4 │5 │6 │7 │8 │Total│
├──────────┼──┼──┼──┼──┼──┼──┼──┼──┼─────┤
│Should pay│10│10│10│10│10│10│10│10│80   │
├──────────┼──┼──┼──┼──┼──┼──┼──┼──┼─────┤
│Payed     │0 │0 │0 │0 │0 │0 │0 │80│80   │
└──────────┴──┴──┴──┴──┴──┴──┴──┴──┴─────┘

最佳(也是唯一)解决方案是:

1 solutions with unique transfer sums. Best solution:
┌─────────────────────────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬────────┐
│Guy #                    │1    │2    │3    │4    │5    │6    │7    │8    │Total│Turnover│
├─────────────────────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────────┤
│Should pay               │10   │10   │10   │10   │10   │10   │10   │10   │80   │        │
├─────────────────────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────────┤
│Has paid                 │0    │0    │0    │0    │0    │0    │0    │80   │80   │        │
├─────────────────────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────────┤
│Gets from the one to left│0.00 │10.00│20.00│30.00│40.00│50.00│60.00│70.00│     │280     │
├─────────────────────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────────┤
│Pays to the one to right │10.00│20.00│30.00│40.00│50.00│60.00│70.00│0.00 │     │280     │
└─────────────────────────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴────────┘

我们看到付款金额增加。尽管#7只有10的债务,但他收到60并且支付70.原因是所有其他人必须积累/积累足够的金额,以支付#8。标准是#8(以及其他每个人)只能从另一个人那里收钱,而不是从多个人那里收钱。

现在考虑一个更复杂的 - 每个都从菜单中自己做出选择。有些人为自己的食物买单,#8负责#1,#3,#5,#7和他自己的付款:

┌──────────┬──┬──┬──┬──┬──┬──┬──┬──┬─────┐
│Guy       │1 │2 │3 │4 │5 │6 │7 │8 │Total│
├──────────┼──┼──┼──┼──┼──┼──┼──┼──┼─────┤
│Should pay│10│25│12│18│16│10│18│15│124  │
├──────────┼──┼──┼──┼──┼──┼──┼──┼──┼─────┤
│Payed     │0 │25│0 │18│0 │10│0 │71│124  │
└──────────┴──┴──┴──┴──┴──┴──┴──┴──┴─────┘

结果非常好。那些为自己付钱的人没有受到影响:

97 solutions with unique transfer sums. Best solution:
┌─────────────────────────┬─────┬─────┬─────┬─────┬─────┬────┬────┬────┬─────┬────────┐
│Guy #                    │1    │3    │5    │7    │8    │2   │4   │6   │Total│Turnover│
├─────────────────────────┼─────┼─────┼─────┼─────┼─────┼────┼────┼────┼─────┼────────┤
│Should pay               │10   │12   │16   │18   │15   │25  │18  │10  │124  │        │
├─────────────────────────┼─────┼─────┼─────┼─────┼─────┼────┼────┼────┼─────┼────────┤
│Has paid                 │0    │0    │0    │0    │71   │25  │18  │10  │124  │        │
├─────────────────────────┼─────┼─────┼─────┼─────┼─────┼────┼────┼────┼─────┼────────┤
│Gets from the one to left│0.00 │10.00│22.00│38.00│56.00│0.00│0.00│0.00│     │126     │
├─────────────────────────┼─────┼─────┼─────┼─────┼─────┼────┼────┼────┼─────┼────────┤
│Pays to the one to right │10.00│22.00│38.00│56.00│0.00 │0.00│0.00│0.00│     │126     │
└─────────────────────────┴─────┴─────┴─────┴─────┴─────┴────┴────┴────┴─────┴────────┘

然后一个案例显然好人清空了所有的口袋,并支付了124美元:

┌──────────┬──┬──┬──┬──┬──┬──┬──┬──┬─────┐
│Guy       │1 │2 │3 │4 │5 │6 │7 │8 │Total│
├──────────┼──┼──┼──┼──┼──┼──┼──┼──┼─────┤
│Should pay│10│25│12│18│16│10│18│15│124  │
├──────────┼──┼──┼──┼──┼──┼──┼──┼──┼─────┤
│Payed     │17│20│10│19│10│20│16│12│124  │
└──────────┴──┴──┴──┴──┴──┴──┴──┴──┴─────┘

非常好!没钱可动:

67 solutions with unique transfer sums. Best solution:
┌─────────────────────────┬────┬────┬────┬────┬─────┬─────┬────┬────┬─────┬────────┐
│Guy #                    │1   │3   │4   │8   │5    │6    │7   │2   │Total│Turnover│
├─────────────────────────┼────┼────┼────┼────┼─────┼─────┼────┼────┼─────┼────────┤
│Should pay               │10  │12  │18  │15  │16   │10   │18  │25  │124  │        │
├─────────────────────────┼────┼────┼────┼────┼─────┼─────┼────┼────┼─────┼────────┤
│Has paid                 │17  │10  │19  │12  │10   │20   │16  │20  │124  │        │
├─────────────────────────┼────┼────┼────┼────┼─────┼─────┼────┼────┼─────┼────────┤
│Gets from the one to left│7.00│0.00│2.00│1.00│4.00 │10.00│0.00│2.00│     │26      │
├─────────────────────────┼────┼────┼────┼────┼─────┼─────┼────┼────┼─────┼────────┤
│Pays to the one to right │0.00│2.00│1.00│4.00│10.00│0.00 │2.00│7.00│     │26      │
└─────────────────────────┴────┴────┴────┴────┴─────┴─────┴────┴────┴─────┴────────┘

最后一个案例,所有都支付了相等的金额,但后来解决了以不同方式支付的义务:应该支付相同的费用,但支付方式不同:

┌──────────┬──┬──┬──┬──┬──┬──┬──┬──┬─────┐
│Guy       │1 │2 │3 │4 │5 │6 │7 │8 │Total│
├──────────┼──┼──┼──┼──┼──┼──┼──┼──┼─────┤
│Should pay│10│10│10│10│10│10│10│10│80   │
├──────────┼──┼──┼──┼──┼──┼──┼──┼──┼─────┤
│Payed     │7 │20│10│5 │10│10│6 │12│80   │
└──────────┴──┴──┴──┴──┴──┴──┴──┴──┴─────┘

微小的营业额:

54 solutions with unique transfer sums. Best solution:
┌─────────────────────────┬────┬────┬────┬─────┬─────┬────┬────┬────┬─────┬────────┐
│Guy #                    │1   │8   │7   │4    │2    │3   │5   │6   │Total│Turnover│
├─────────────────────────┼────┼────┼────┼─────┼─────┼────┼────┼────┼─────┼────────┤
│Should pay               │10  │10  │10  │10   │10   │10  │10  │10  │80   │        │
├─────────────────────────┼────┼────┼────┼─────┼─────┼────┼────┼────┼─────┼────────┤
│Has paid                 │7   │12  │6   │5    │20   │10  │10  │10  │80   │        │
├─────────────────────────┼────┼────┼────┼─────┼─────┼────┼────┼────┼─────┼────────┤
│Gets from the one to left│0.00│3.00│1.00│5.00 │10.00│0.00│0.00│0.00│     │19      │
├─────────────────────────┼────┼────┼────┼─────┼─────┼────┼────┼────┼─────┼────────┤
│Pays to the one to right │3.00│1.00│5.00│10.00│0.00 │0.00│0.00│0.00│     │19      │
└─────────────────────────┴────┴────┴────┴─────┴─────┴────┴────┴────┴─────┴────────┘

如何进行此计算

正如我们通过蛮力所做的那样,它意味着产生参与者数量的所有权利。这可能是棘手的部分。例如,(1,2,3,4)的所有排列都在下面(逐列编写,以提高可读性):

1 1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3 3 4 4 4 4 4 4
2 2 3 3 4 4 1 1 3 3 4 4 1 1 2 2 4 4 1 1 2 2 3 3
3 4 2 4 2 3 3 4 1 4 1 3 2 4 1 4 1 2 2 3 1 3 1 2
4 3 4 2 3 2 4 3 4 1 3 1 4 2 4 1 2 1 3 2 3 1 2 1

你最好搜索这一代。如果它在一个循环中发生就没问题。关键是你可以访问一列(如果行是行,则可以是行)。

伪:

// NOTE: The data is written as arrays
//       For example "0 0 0 0" implies a 4-element array (vector) of integers
//       Of course there may be other number of participants ("guys"),
//        then we need "other-element" arrays, for example 7-element ones
//       The code below may require additional looping

ToPay = 100 100 100 100 // Topmost example in this answer
HasPayed = 0 0 0 400 // Ditto

// Calculate debt
// This probably requires a loop from 1...4
Debt[n] = ToPay[n] - HasPayed[n] // Debt is now: 100 100 100 -300

smallest = 9999999 // Sufficiently big initial value

:For Row :In [each permutation of (1 2 3 4) // Row is now for example: 2 4 3 1
    Test = Debt[Row] // Test is now for example: 100 -300 100 100
    Accu = [4-element vector of zeroes]
    Accu[1] = Row[1]
    minimum = Row[1]
    s = 2
    :Repeat
        Accu[s] = Accu[s-1] + Row[s]
        minimum = min(minimum, Accu[s]) // We simply grab the smalles element in Accu
        s += 1
    :Until (s > 4)
    // As this is ready, Accu may contain eg. 100 -200 -100 0
    //  and minimum would then contain -200
    sum = 0
    t = 1
    :Repeat
        Accu[t] -= minimum
        sum += Accu[t]
        t += 1
    :Until (t > 4) 
    // When ready, Accu would be eg. 300 0 100 200
    //  and sum would be 300+0+100+200, ie. 600
    :If (sum < smallest)
        [store Row as best so far, for example into "BestRow"]
        [store Accu, for example into BestAccu"]
        smallest = sum
    :End
:End

现在

  • BestRow包含一个人支付另一个人的顺序(来自 从左到右),例如1 2 3 4(= 1付2,2付3,3付4,4付1)。
  • BestAccu包含向右边的人支付的金额,例如100 200 300 0.

可以采用其他标准来实现最好的方式&#34;但是这个解决方案可以最大限度地减少金钱的流动并且#34;并保持交易每人一次付款。

另外需要注意的是,有多种最佳解决方案&#34;,其中一种排列产生与另一种排列相同的最小周转率。对于最后一个例子,同样好的解决方案的数量(最好到最差)是:

48  96  144  144  240  240  480  336  672  432  768  912  960  768  1296  864  1392  1104  1200  1056  1488  1488  1488  1200  1344  1152  1776  1056  1344  1056  1152  1152  1344  768  1104  768  1056  720  912  480  672  528  528  240  576  288  432  192  288  144  240  48  96  48 

...意思是48&#34;最佳解决方案&#34;,96&#34;第二好&#34;等

编辑:

我被告知一个我不正常地假设的标准:一个人只能从另一个人那里收钱。情况并非如此,任何人都可以向其他人提供资金,但可以从任何人,一个人或多人<接收资金

事实证明,上面给出的解决方案已经基本完成了。要解决这个新情况,只需要再处理一下结果。也就是说,现在存在于上述逻辑中的累积,其中连续多个人可能积累越来越多的钱,同时他们自己有助于积累,以便向付了大笔钱的人付出代价(&#34;先生X&#34;) - 需要拆除这种累积,以便它的累积部分直接>支付给X,而不是通过其他参与者。

考虑这种情况:

┌──────────┬──┬──┬──┬──┬──┬──┬─────┐
│Guy       │1 │2 │3 │4 │5 │6 │Total│
├──────────┼──┼──┼──┼──┼──┼──┼─────┤
│Should pay│10│10│20│30│10│20│100  │
├──────────┼──┼──┼──┼──┼──┼──┼─────┤
│Payed     │35│0 │25│0 │0 │40│100  │
└──────────┴──┴──┴──┴──┴──┴──┴─────┘

虽然看起来很简单,但通过头部计算很难解决,因为它是循环的。通过早期的方法,我们得到了&#34;累积&#34;回答:

22 solutions with unique transfer sums. Best solution:
┌─────────────────────────┬──┬──┬──┬──┬──┬──┬─────┬────────┐
│Guy #                    │1 │3 │2 │5 │6 │4 │Total│Turnover│
├─────────────────────────┼──┼──┼──┼──┼──┼──┼─────┼────────┤
│Should pay               │10│20│10│10│20│30│100  │        │
├─────────────────────────┼──┼──┼──┼──┼──┼──┼─────┼────────┤
│Has paid                 │35│25│0 │0 │40│0 │100  │        │
├─────────────────────────┼──┼──┼──┼──┼──┼──┼─────┼────────┤
│Gets from the one to left│30│5 │0 │10│20│0 │     │65      │
├─────────────────────────┼──┼──┼──┼──┼──┼──┼─────┼────────┤
│Pays to the one to right │5 │0 │10│20│0 │30│     │65      │
└─────────────────────────┴──┴──┴──┴──┴──┴──┴─────┴────────┘

然后我们可以解决每一个的债务,这是第二行 - 第三行(债务为正):

┌───┬──┬──┬──┬───┬──┐
│-25│-5│10│10│-20│30│
└───┴──┴──┴──┴───┴──┘

使用它,我们可以解决一些名为&#34;积累 - 这是第五行 - 债务:

┌──┬─┬─┬──┬──┬─┐
│30│5│0│10│20│0│
└──┴─┴─┴──┴──┴─┘

由此,我们可以解决哪些付款可以从&#34;付款到正确的&#34;一个&#34;付钱的人#n&#34; - 这只是通过比较累积的,并将累积的最后一个元素与第一个元素进行比较(因为这个问题是循环的)。第一个比较是(30 <5),然后是(5 <0),然后是(0 <10)等;最后一个是(0 <30):

┌─┬─┬─┬─┬─┬─┐
│0│0│1│1│0│1│
└─┴─┴─┴─┴─┴─┘

1表示下一次累积大于当前累积 - 这些是现在可直接转入#n的付款。

谁是#n? #n 是一系列之后的下一个人。插槽3和插槽4(上面第一个答案中的#2和#5)后面是第6个人 - 他是#2和#5现在支付的那个,而其他支付保持不变。

这个编码不是很棘手,但是依赖于语言,因此我将其留给实现者。只需在每组中向前推进累积,直到(并包括)一组之后的每个零,并重新解决付款问题。答案很好:

┌──────────┬──┬──┬──┬──┬──┬──┐
│Guy       │1 │3 │2 │5 │6 │4 │
├──────────┼──┼──┼──┼──┼──┼──┤
│Should pay│10│20│10│10│20│30│
├──────────┼──┼──┼──┼──┼──┼──┤
│Payed     │35│25│0 │0 │40│0 │
├──────────┼──┼──┼──┼──┼──┼──┤
│Pays to   │3 │  │6 │6 │  │1 │
├──────────┼──┼──┼──┼──┼──┼──┤
│Amount    │5 │  │10│10│  │30│
└──────────┴──┴──┴──┴──┴──┴──┘

答案很有意思,因为那个#1,实际上是一个超额预算的人,必须向3号人支付5美元。发生这种情况是因为#4(最右边)的债务为30,他必须向另一个人支付 - 这会导致超额支付&#34;到#1,但作为#1的邻居#3需要从某个地方获得5,#1传递给他。然后其余部分完美契合,#6从#2和#5获得20。标准是尽量减少付款并找到最佳解决方案,对吧? : - )

一些例子(情况和解决方案)。低于2的同等付款人:

 ┌──────────┬──┬──┬──┬─┬─┬──┬──┬──┬─────┐  ┌───────┬─┬─┬──┬──┬─┬─┬──┬──┐ 
 │Guy       │1 │2 │3 │4│5│6 │7 │8 │Total│  │Guy    │1│5│6 │8 │2│4│7 │3 │ 
 ├──────────┼──┼──┼──┼─┼─┼──┼──┼──┼─────┤  ├───────┼─┼─┼──┼──┼─┼─┼──┼──┤ 
 │Should pay│7 │11│13│8│5│10│12│14│80   │  │Pays to│ │2│2 │2 │ │1│1 │1 │ 
 ├──────────┼──┼──┼──┼─┼─┼──┼──┼──┼─────┤  ├───────┼─┼─┼──┼──┼─┼─┼──┼──┤ 
 │Payed     │40│40│0 │0│0│0 │0 │0 │80   │  │Amount │ │5│10│14│ │8│12│13│ 
 └──────────┴──┴──┴──┴─┴─┴──┴──┴──┴─────┘  └───────┴─┴─┴──┴──┴─┴─┴──┴──┘ 

一个大的和一些小的付款人:

 ┌──────────┬──┬───┬──┬──┬──┬──┬──┬──┬──┬──┬─────┐  ┌───────┬─┬──┬──┬──┬──┬──┬──┬─┬──┬─┐ 
 │Guy       │1 │2  │3 │4 │5 │6 │7 │8 │9 │10│Total│  │Guy    │1│3 │7 │4 │10│6 │8 │2│5 │9│ 
 ├──────────┼──┼───┼──┼──┼──┼──┼──┼──┼──┼──┼─────┤  ├───────┼─┼──┼──┼──┼──┼──┼──┼─┼──┼─┤ 
 │Should pay│10│10 │10│12│10│19│11│33│6 │12│133  │  │Pays to│2│2 │2 │2 │2 │2 │2 │ │9 │1│ 
 ├──────────┼──┼───┼──┼──┼──┼──┼──┼──┼──┼──┼─────┤  ├───────┼─┼──┼──┼──┼──┼──┼──┼─┼──┼─┤ 
 │Payed     │5 │112│0 │0 │0 │1 │0 │0 │15│0 │133  │  │Amount │6│10│11│12│12│18│33│ │10│1│ 
 └──────────┴──┴───┴──┴──┴──┴──┴──┴──┴──┴──┴─────┘  └───────┴─┴──┴──┴──┴──┴──┴──┴─┴──┴─┘

非常不规律:

 ┌──────────┬──┬──┬──┬──┬──┬──┬──┬──┬─┬──┬─────┐  ┌───────┬──┬──┬─┬─┬─┬─┬─┬──┬──┬─┐ 
 │Guy       │1 │2 │3 │4 │5 │6 │7 │8 │9│10│Total│  │Guy    │1 │10│4│9│5│3│6│7 │8 │2│ 
 ├──────────┼──┼──┼──┼──┼──┼──┼──┼──┼─┼──┼─────┤  ├───────┼──┼──┼─┼─┼─┼─┼─┼──┼──┼─┤ 
 │Should pay│10│10│5 │12│10│19│11│33│6│12│128  │  │Pays to│10│  │9│5│3│ │2│2 │2 │ │ 
 ├──────────┼──┼──┼──┼──┼──┼──┼──┼──┼─┼──┼─────┤  ├───────┼──┼──┼─┼─┼─┼─┼─┼──┼──┼─┤ 
 │Payed     │7 │50│10│10│6 │12│1 │10│7│15│128  │  │Amount │3 │  │2│1│5│ │7│10│23│ │ 
 └──────────┴──┴──┴──┴──┴──┴──┴──┴──┴─┴──┴─────┘  └───────┴──┴──┴─┴─┴─┴─┴─┴──┴──┴─┘ 

正如我们所见,解决方案看起来非常理想。