Since you have a limit on the number of items that you can pick, you can do it with a reasonably straightforward algorithm.
The algorithm produces the possible sums in "generations". Each element of a generation consists of a number representing the sum, and a N-tuple of indexes in M
that were used to build that sum.
Generation zero is empty; generation X+1
is produced by walking the generation X
, and adding the elements of M
to each value of that generation, and recording their sum for the next generation X+1
.
Before computing the sum, check its N-tuple for the presence of the index of the number that you are about to add. If it's there, skip the number. Next, check the sum: if it is already present among the X+1
sums, ignore it; otherwise, record the new sum, along with the new N-tuple of indexes (append the index of the number that you added to the N-tuple from the generation X
).
Here is how this would work for your inputs:
Generation 0: empty
Generation 1:
1 - {0}
3 - {1}
5 - {2}
14 - {4}
Generation 2:
4 - {0, 1}
6 - {0, 2}
8 - {1, 2}
10 - {2, 3}
15 - {0, 4}
17 - {1, 4}
19 - {2, 4}
Generation 3:
9 - {0, 1, 2}
11 - {0, 2, 3}
13 - {1, 2, 3}
18 - {0, 1, 4}
20 - {0, 2, 4}
22 - {1, 2, 4}
24 - {2, 3, 4}
Generation 4:
14 - {0, 1, 2, 3}
23 - {0, 1, 2, 4}
25 - {0, 2, 3, 4}
27 - {1, 2, 3, 4}
You can now search through the four generations for a number that is closest to your target number k
.