Сумма значений массива с суммой, равной X

У меня целочисленная коллекция. Мне нужно получить все возможности, что сумма значений равна X.

Мне нужно что - то вроде этого .

Его можно написать на: delphi, c #, php, RoR, python, cobol, vb, vb.net.

Ответов (2)

Решение

Это проблема суммы подмножества . И это NP-Complete .

Единственный способ реализовать это - сгенерировать все возможные комбинации и сравнить итоговые значения. Однако методы оптимизации существуют.

Вот один на C#:

static class Program
{
    static int TargetSum = 10;
    static int[] InputData = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    static void Main()
    {
        // find all permutations
        var permutations = Permute(InputData);

        // check each permutation for the sum
        foreach (var item in permutations) {

            if (item.Sum() == TargetSum) {

                Console.Write(string.Join(" + ", item.Select(n => n.ToString()).ToArray()));
                Console.Write(" = " + TargetSum.ToString());
                Console.WriteLine();

            }
        }

        Console.ReadKey();
    }

    static IEnumerable<int[]> Permute(int[] data) { return Permute(data, 0); }

    static IEnumerable<int[]> Permute(int[] data, int level)
    {
        // reached the edge yet? backtrack one step if so.
        if (level >= data.Length) yield break;

        // yield the first #level elements
        yield return data.Take(level + 1).ToArray();

        // permute the remaining elements
        for (int i = level + 1; i < data.Length; i++) {
            var temp = data[level];
            data[level] = data[i];
            data[i] = temp;

            foreach (var item in Permute(data, level + 1))
                yield return item;

            temp = data[i];
            data[i] = data[level];
            data[level] = temp;
        }

    }
}

Динамическое программирование обеспечит наилучшее время выполнения для точного решения. Страница задачи суммы подмножества в Википедии есть некоторый псевдокод для алгоритма. По сути, вы упорядочиваете все числа и складываете все возможные последовательности в таком порядке, чтобы минимизировать количество добавлений. Среда выполнения псевдополиномиальна.

Для полиномиального алгоритма вы можете использовать алгоритм приближения . Псевдокод также доступен на странице задачи суммы подмножества .

Из двух алгоритмов я бы выбрал алгоритм динамического программирования, поскольку он прост и хорошо работает с большинством наборов данных.

Однако, если все целые числа неотрицательны и соответствуют описанию на странице Википедии, вы действительно можете сделать это за полиномиальное время с помощью алгоритма аппроксимации.