I don't think there is a "smart" algorithm that can solve this in linear, or even polynomial, time. I'm afraid the only viable approach is to try all the possible combinations, and choose the best one. You can, though, use some techniques that conceptually are like branch and bound to get to the result faster.
I would do it like this.
Basic algorithm
First, I would generate all the possible combinations. For each of your N number you can choose to sum it or to subtract it, so you have 2 choices. That means that overall you have a total of 2^N possible choices. In your example, with N=3, these would be: ---
, --+
, -+-
, -++
, +--
, +-+
, ++-
, +++
. (This is like counting in binary, from 0 = 000 to 7 = 111).
At this point you have to "execute" each sequence. With these numbers (5, 3, 7
), the first sequence means -5 -3 -7. You must run it one step at a time, and each time check that you aren't exceeding the target M, because it is required. Since your initial value A is 5, this would lead to: 5-5=0, and since 0<10 you can continue. Then, 0-3=-3, which is less than 10, so it's ok. Then, -3-7=-10 and since this is the last operation we don't have to check that it is less than 10. So the sequence is valid, and we have that for ---
the result is -10. This is the best result so far (as it is the only one), so let's save the sequence as best sequence and the final result.
Then, let's move to the next sequence, --+
. Again it's valid and the final result is 4. This is the best result so far, so we can save this sequence --+, overwriting the previous best result.
Going on, at -++
we will find the best result, 10, which can't be improved, thus we could stop there. If we don't reach M, we have to evaluate all the sequences, and at the end we will have the best one. There might be more than one that leads to the best result, for example if you have duplicate numbers (3 3
can be either +3 -3 or -3 +3, the sequences are different but the result is obviously the same), so you might want to store the best solutions in a vector, instead of keeping just one.
This would be the basic algorithm. Now, let's try to optimize it a little.
Optimized algorithm
Until now we have generated all the possible sequences (from ---
to +++
) and evaluated them all, one at a time. In some cases, though, evaluating them all is a waste of time. For example, let's say that the initial number is again A=5 and the target is M=10. If the sequence was like 6 3 4
, at a certain point we would try to evaluate +--
, but that would immediately fail because the first intermediate result would exceed the maximum value (5+6=11). Following the basic algorithm we would move on to evaluate +-+
, but it doesn't make sense: it will obviously fail, for the same reason, at the same step (the first digit, that is, 5+6). The invalid sequence started with +
, and all the successive choices of sign don't matter: all the sequences starting with +
are necessarily invalid and can be discarded. So it means that if we find an invalid sequence, we can discard all the others that start like it.
To do this we can save all the sequences in a tree, which relates each choice of a sign to the previous one. Then, once we find an invalid solution we can discard all the others that begin like that one. For example, the tree could be saved like:
Root
/ \
/ \
/ \
/ \
/ \
- +
/ \ / \
- + - +
/ \ / \ / \ / \
- + - + - + - +
and each sequence corresponds to the series of nodes that must be explored to reach one of the leaves. When you visit the tree, for every node you can calculate and store the value of the sequence so far. So when you reach the + at the first level you see that 5+6=11, which is too much, and you mark the entire node as invalid, thus avoiding to explore all the possible variants. Of course, with N=3 numbers it won't make much difference, as there are only a total of 2^3=8 sequences. But for N=20 they would be one million, and the time savings could be significant.