People too easily give up NP-complete problems. Just because the NP problem is complete does not mean that in the general case there are no more efficient algorithms. That is, you cannot guarantee that for all inputs there is an answer that can be calculated faster than brute force search, but for many problems you probably have methods that are faster than a full search for most inputs.
For this problem, there are certainly โpervertedโ sets of numbers that will lead to the worst search time, because you can say that there is a large vector of integers, but only one solution, and you should end up trying a very large number of combinations.
But for naughty sets, there are probably many solutions, and an effective way to โtoppleโ over a good split will work much faster than NP time.
How you decide this will depend on what you expect from more general options. It also matters if the integers are positive or negative values โโare allowed.
In this case, I will assume that:
- N is small with respect to the length of the vector
- All integers are positive.
- Integers cannot be reused.
Algorithm:
- Sorting a vector, v.
- Eliminate items in excess of M. They cannot be part of any solution.
- Add all the remaining numbers to v, divide them by N. If the result is less than M, there is no solution.
- Create a new array w, whose size is v. For each w [i] we summarize all the numbers in v [i + 1 - end]
So, if v were 5 4 3 2 1, w would be 10, 6, 3, 1, 0.
Until you find enough sets:
- Choose the largest number, x, if it is equal to M, emits a set of solutions with only x and removes it from the vector, remove the first element from w.
Still not enough sets? (probably), then again until you find enough sets:
- The solution theory is ([a, b, c], R), where [a, b, c] is a partial set of elements v and the remainder R. R = M-sum [a, b, c]. Extension of the theory - adding a number to a partial set and subtracting this number from R. As theories expand, if R == 0, this is a possible solution.
Create theories recursively: iterate over elements v, like v [i], creating theories, ([v [i]], R), and now recursively expand each theory from one part of v. Binary search in v to find the first element equal to or less than R, v [j]. Start with v [j] and continue each theory with elements v from j, until R> w [k].
The numbers v [j] to v [k] are the only numbers that are used to expand the theory and still get R to 0. Numbers larger than v [j] will make R negative. Less than v [k], and more numbers are left in the array, even if you used all of them to get R to 0