特定の合計を構成するリスト内の数値を見つける必要があります。
Sum: 500
Subtotals: 10 490 20 5 5
In the end I need: {10 490, 490 5 5}
この種の問題を何と呼びますか。それを効率的に解決するアルゴリズムはありますか?
これはナップザック問題であり、NP 完全問題です。つまり、既知の効率的なアルゴリズムはありません。
Subtotals 配列に正でない要素がなく、どの要素も Sum よりも大きくないと仮定しましょう。小計の配列を並べ替え、最後に 0 を追加して末尾の合計の配列を作成できます。あなたの例では、次のようになります。
Subtotals: (490, 20, 10, 5, 5)
PartialSums: (530, 40, 20, 10, 5, 0)
ここで、任意の「残りの合計」S、位置 i、および「現在のリスト」L に対して、問題 E(S, i, L):
E(0, i, L) = (print L) があります。
E(S, i, L) | (PartialSums[i] < S) = (なし)。
E(S, i, L) = E(S, i+1, L), E(S-Subtotals[i], j, L||Subtotals[i])、j は Subtotals lesser の最初の要素のインデックス(S-Subtotals[i]) または i+1 のいずれか大きい方以上。
問題は E(Sum, 0, {}) です。
もちろん、重複には問題があります (リストに別の 490 番号があった場合、このアルゴリズムは 4 つの解を出力します)。それが必要でない場合は、ペアの配列 (値、多重度) を使用すると役立つ場合があります。
PS問題のサイズが十分に小さい場合は、動的計画法も検討できます。
最終セットに Sum がない場合、解決策はありません。それ以外の場合は、ソリューションを Sum から 0 にバックトラックし、前のセットに [value] と [value-subtotal] が含まれているかどうかを確認します。
例:
(10、490、20、5、5)
セット:
(0)
(0, 10)
(0, 10, 490, 500)
(0, 10, 20, 30, 490, 500) (510, 520 - discarded)
(0, 5, 10, 15, 20, 25, 30, 35, 490, 495, 500)
(0, 5, 10, 15, 20, 25, 30, 35, 40, 490, 495, 500)
前のセットから: [500-5] 前のセット、[495-5] 前のセット、[490-20] 前のセットにない ([490] は)、[490-490] は 0、結果の答え {5 、5、490}。