これは実際、複式簿記の概念が役立つ仕事のように見えます。
トランザクションは、次のように簿記エントリとして構造化できます。
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
そして、あなたはそれを持っています。各取引で、残高が常にゼロになるように、1 つの元帳口座に入金し、別の口座から引き落とします。最後に、各アカウントに適用されるトランザクションの最小数を計算して、アカウントをゼロに戻します。
この単純なケースでは、Bill から Alice への単純な $4 の送金です。あなたがする必要があるのは、追加されたトランザクションごとに、少なくとも 1 つのアカウント (できれば 2 つ) をゼロに減らすことです。より複雑な場合を考えてみましょう:
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
明らかに、これは 4 つの手で逆転する可能性があります (そこに到達するのに必要な手数は 4 つだけなので) が、賢明に最初の手を選択しない場合(Edie->Bill $2)
、5 つが最小限で済みます。
この特定の問題は、次のルールで解決できます。
- (1) 2 つの残高を消去できる場合は、それを実行します。
- (2) それ以外の場合は、1 つのバランスを一掃し、次の動きで 2 つを一掃する準備ができている場合は、それを実行します。
- (3) それ以外の場合は、いずれか 1 つの残高を消去します。
その結果、次のシーケンスになります。
- (a) [1] 該当なし、[2] は で達成できます
Alan->Bill $5
。
- (b) [1] でできます
Chas->Bill $20
。
- (c) と (d)、Doug、Edie、Fred と同様の推論で、合計 4 回の移動。
ただし、可能性の数が少ないため、これは単純に機能します。人数が増え、グループの相互関係がより複雑になると、必要な最小手数を見つけるために徹底的な検索が必要になる可能性が高くなります (基本的には上記のルール 1、2、および 3 ですが、より深く処理するために拡張されます)。 .
それが、あらゆる状況で最小数のトランザクションを提供するために必要なことだと思います. ただし、それは最良の回答には必要ない場合があります (この場合の最良の回答は、最大の「1 ドルあたりの価値」を意味します)。基本的な 1/2/3 ルール セットでさえ、目的に対して十分な答えが得られるかもしれません。