这是一个更一般的问题,不是语言特定的。更多关于想法和算法的使用。
系统如下:
它登记朋友之间的小额贷款Alice
和Bill
要去吃午饭,比尔的卡坏了,所以爱丽丝付了他10美元的饭钱。
第二天,查尔斯和他在火车站见面,没钱买票,于是他花5美元买了一张。
那天晚些时候Bill
从Charles
借了5美元,从Bill
借了1美元给她的朋友买礼物。
现在,假设他们都在系统中注册了该事务,则如下所示:
Alice -> Bill $10
Bill -> Alice $1
Bill -> Charles $5
Charles -> Alice $5
所以,现在,唯一需要做的事情就是给她4美元(他给了她1美元,然后把他的5美元转到了alredy),然后他们就处于初始状态。
如果我们将其扩展到多个不同的人,有多个事务,那么什么样的算法可以获得尽可能少的事务?
最佳答案
实际上,这看起来像是一项复式记账概念可以帮助完成的工作。
您的交易可以被构造为记账分录,因此:
Alice Bill Charles Balance
Alice -> Bill $10 10 10- 0 0
Bill -> Alice $1 9 9- 0 0
Bill -> Charles $5 9 4- 5- 0
Charles -> Alice $5 4 4- 0 0
你拿到了。在每笔交易中,您贷记一个分类账账户,借记另一个分类账账户,以便余额始终为零最后,您只需计算出应用于每个帐户的最小事务数,将其返回到零。
对于这个简单的例子,这是一个简单的4美元从比尔转移到爱丽丝。你需要做的是减少至少一个帐户(但最好是两个)为零,每增加一个交易。假设你有更复杂的事情:
Alice Bill Charles Balance
Alice -> Bill $10 10 10- 0 0
Bill -> Alice $1 9 9- 0 0
Bill -> Charles $5 9 4- 5- 0
Charles -> Alice $5 4 4- 0 0
Charles -> Bill $1 4 5- 1 0
那么所需的交易将是:
Bill -> Alice $4 0 1- 1 0
Bill -> Charles $1 0 0 0 0
不幸的是,有些州这种简单的贪婪策略并不能产生最佳的解决方案(值得称赞的是
j_random_hacker
指出了这一点)。一个例子是: Alan Bill Chas Doug Edie Fred Bal
Bill->Alan $5 5- 5 0 0 0 0 0
Bill->Chas $20 5- 25 20- 0 0 0 0
Doug->Edie $2 5- 25 20- 2 2- 0 0
Doug->Fred $1 5- 25 20- 3 2- 1- 0
很明显,这可以在四个动作中逆转(因为四个动作是到达目的地所需的全部),但是,如果你不明智地选择了第一个动作
(Edie->Bill $2)
,那么五个动作是你能逃脱的最小动作。您可以使用以下规则解决此特定问题:
(1)如果你能擦去两个天平,就这样做。
(2)否则,如果你能在下一步中抹掉一个平衡并准备好抹掉两个平衡,那么就这样做。
(3)否则,清除任何一个天平。
这将导致以下顺序:
(a)[1]不适用,[2]可通过
Alan->Bill $5
实现。(b)[1]可以用
Chas->Bill $20
来完成。(c)和(d),与道格、伊迪和弗雷德的推理相似,共四步。
然而,这仅仅是因为可能性很小。随着人数的增加,团队之间的关系变得更加复杂,您很可能需要进行详尽的搜索,以找到所需的最少移动次数(基本上是上面的规则1、2和3,但为了处理更深入的问题而进行了扩展)。
我想这就是在任何情况下给你最少的交易数量所需要的。然而,这可能不是最好的答案所需要的(最好的,在这种情况下,意味着最大的“砰砰”)。可能即使是基本的1/2/3规则集也会为您的目的提供足够好的答案。