11

数の集合があるとしましょう

1、2、3、4、5、6、7、8、9、10

合計が既知の数、たとえば 18 に等しくなるように、数のセット内のいくつかの組み合わせを見つけたいと考えています。5、6、7 が一致することがわかります (5+6+7=18)。 .

組み合わせ内の数字を繰り返すことはできず、セット内の数字は連続していない場合があります。

そのための C# プログラムを作成しました。このプログラムはランダムに数字をピックアップして組み合わせを形成し、組み合わせの合計が既知の数字と等しいかどうかをチェックします。ただし、プログラムが見つけた組み合わせが繰り返される可能性があり、進行が有効ではなくなります。

そのような組み合わせを見つけるための効率的なアルゴリズムがあるかどうか疑問に思っています。

これが私のコードの一部です。

        int Sum = 0;
        int c;
        List<int> Pick = new List<int>();
        List<int> Target = new List<int>() {some numbers}

        Target.Sort();

            while (!Target.Contains(Sum))
            {
                if (Sum > Target[Target.Count - 1])
                {
                            Pick.Clear();
                            Sum = 0;

                }
                while (true)
                {
                    if (Pick.IndexOf(c = Math0.rand(0, Set.Count - 1)) == -1)
                    {
                        Pick.Add(c);
                    }

                    //Summation Pick
                    Sum = 0;
                    for (int i = 0; i < Pick.Count; i++)
                        Sum += Set[Pick[i]];

                    if (Sum >= Target[Target.Count - 1])
                        break;
                }


            }

            Result.Add(Pick);
4

2 に答える 2

29

You can use recursion. For any given number in the set, find the combinations of smaller numbers that adds up to the number:

public static IEnumerable<string> GetCombinations(int[] set, int sum, string values) {
  for (int i = 0; i < set.Length; i++) {
    int left = sum - set[i];
    string vals = set[i] + "," + values;
    if (left == 0) {
      yield return vals;
    } else {
      int[] possible = set.Take(i).Where(n => n <= sum).ToArray();
      if (possible.Length > 0) {
        foreach (string s in GetCombinations(possible, left, vals)) {
          yield return s;
        }
      }
    }
  }
}

Usage:

int[] set = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

foreach (string s in GetCombinations(set, 18, "")) {
  Console.WriteLine(s);
}

Output:

1,2,4,5,6,
3,4,5,6,
1,2,3,5,7,
2,4,5,7,
2,3,6,7,
1,4,6,7,
5,6,7,
1,2,3,4,8,
2,3,5,8,
1,4,5,8,
1,3,6,8,
4,6,8,
1,2,7,8,
3,7,8,
2,3,4,9,
1,3,5,9,
4,5,9,
1,2,6,9,
3,6,9,
2,7,9,
1,8,9,
1,3,4,10,
1,2,5,10,
3,5,10,
2,6,10,
1,7,10,
8,10,
于 2012-05-24T14:12:38.130 に答える
1

可能な代替方法。このような小さなセットでは、ブルート フォースを使用できます。セット{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}には 10 個の要素があり、各要素は存在する場合と存在しない場合があります。これは、0 (= 0b0000000000) から 1023 (= 0b1111111111) までの 2 進数にマッピングできます。0 から 1023 までの数値をループし、数値の 2 進数表現のセット ビットに対応するサブセットの合計をチェックします。

この特定の質問にはあまり役に立たないかもしれませんが、特定のセットのすべての可能なサブセットを生成する良い方法です。

于 2012-05-24T15:22:19.870 に答える