Ok, Munters heeft m'n source gekregen als alles goed gaat
Ik ga toch ff tijd maken om mijn methode uit te leggen, of althans een poging te doen
Om te beginnen : de triviale gevallen. Namelijk 0 en 1 getallen zijn opgegeven. Als je geen getallen hebt kun je geen ander getal 'maken', dus geen oplossing. Met 1 getal is 't simpel : gewoon dat getal pakken

Dus als het gegeven getal datgene is dat je wil, dan heb je de oplossing door dat getal te nemen, anders is er geen oplossing.
Dan de kleintjes : 2 getallen gegeven. Dat doe ik uiteraard brute force, lettende op de commutativiteit van de optelling en de vermenigvuldiging, en dus heb ik 6 mogelijkheden :
code:
1
2
3
4
5
6
| getal1 + getal2
getal1 * getal2
getal1 / getal2
getal1 - getal2
getal2 / getal1
getal2 - getal1 |
Meer kan niet.
Ok, alle andere doe ik recursief. Jawel

Neem ff aan dat ik n waarden binnen krijg (bvb n=6 of n=7 voor de contest). Ik kies dan willekeurig 2 waarden uit deze verzameling. Op dit paar getallen kan ik, net als hierboven, 6 mogelijkheden uitproberen. Uit de set van n getallen schrap ik dan de 2 die ik koos, en ik plaats het resultaat van 1 van de 6 mogelijkheden terug. Ik hou dan een set van n-1 getallen over, die ik recursief behandel. Iedere oproep doet m'n set met 1 waarde afnemen, en dus kom ik snel genoeg bij 2, en die doe ik dus brute force (zie hoger). Voor ieder paar probeer ik de 6 mogelijkheden. En dat doe ik voor ieder paar dat mogelijk is. Let op : volgorde maakt niet uit, dus eigenlijk moet ik zeggen : voor iedere deelverzameling van 2 elementen. Als n=7 dan zijn er dat 7! / (5!2!) = 21. En voor iedere deelverzameling dus 6 mogelijkheden, zodat ik dus 21*6 recursieve oproepen moet doen in 't slechtste geval. Dus een 7-waarden probleem oplossen is in 't slechtste geval 126 6-waarden problemen oplossen. Analoog : een 6-waarden probleem oplossen is worst case 6*(6!/(4!2!)) = 6*15 = 90 5-waarden problemen, etc.
Waarom die deelverzameling van 2 elementen ? Wel, het idee kreeg ik omdat een oplossing, als deze bestaat, altijd zonder haakjes kan geschreven worden als een postfixuitdrukking. Wat de vorm ook is van die uitdrukking, je moet altijd op een zeker moment beginnen door 2 elementen te nemen (welke weet je dus niet) en daarop een binaire operatie toe te passen. Dan heb je een postfixuitdrukking met 1 waarde minder, en daarop kan je dezelfde redenering toepassen. Ik kan bewijzen dat je op die manier _alle_ mogelijke schikkingen van de n getallen tegenkomt, ongeacht de bewerkingen in de uitdrukking en ongeacht of er in de uitdrukking nu haakjes staan, teveel of niet, etc.
Dat is een eerste deel. Als bij een bepaalde mogelijkheid de recursieve oproepen een 2-waardenprobleem bekomen, en deze blijkt een oplossing te hebben, dan wordt een postfixuitdrukking opgebouwd, van achter naar voor dus.
De functie die de oplossing vind, weet dat de oplossing gegeven wordt door - ik zeg maar wat - getal1 * getal2, en genereert daarbij de postfixuitdrukking '%1%2*' (%x wil zeggen : het zoveelste getal dat de functie binnen kreeg) en geeft die terug aan de oproeper. Die kreeg 3 waarden binnen, maar weet wat hij doorgaf aan de functieoproep die het 2-waardenprobleem afhandelde. Stel dat - terug als voorbeeld - deze als deelverzameling van 2 elementen uit de 3 de eerste en de derde waarde koos, en de som maakte. Hij weet dus dat het eerste getal wat de opgeroepen functie zag voor hem het tweede getal is, en het tweede getal wat de opgeroepen functie zag voor hem de som is van 't eerste en 't derde getal. Hij zal de postfixuitdrukking dus vertalen naar : '%2%1%3+*' (in de originele dus %1->%2 en %2->%1%3+, wel _tegelijkertijd_ aanpassen om neveneffecten te vermijden). Zo gaat het door tot de eerste oproep, dus die van de main. Deze heeft dan de postfixuitdrukking die het resultaat oplevert. Maar de waarden staan niet noodzakelijk in volgorde, 'k kan ook een permutatie zijn, bvb (3-waardenprobleem) '%2%1+%3*'. Daarom worden de waarden gepermuteerd, zodat ze in volgorde van de postfixuitdrukking staan. Het is dan een koud kunstje om de postfixuitdrukking te vertalen naar een infixuitdrukking. Dat doe ik door een boom op te bouwen die de postfixuitdrukking weergeeft (is heel eenvoudig). Bewerkingen krijgen een prioriteit mee in de boom. Dan 'traverse' ik de boom infix, dus ik bepaal (recursief) de infixuitdrukking voor de linker subboom, dan voor de rechter subboom, en ik plak er de bewerking tussen. Rekening houdend met de prioriteiten van de bewerkingen zie ik meteen ook of rond de infixuitdrukking van de linker en/of rechter subboom haakjes moeten, zodat ik alleen haakjes zet als ze absoluut noodzakelijk zijn...
Oh, het bepalen van de postfix uitdrukking kan eigenlijk makkelijker als je ze 'on the fly' maakt en steeds meegeeft bij een volgende recursieve oproep. Mijn methode vraagt veel meer tijd door de 'vertalingen' van de %x tussen de oproepen door. Maar er is een groot voordeel : je hebt maar 1 oplossing van doen, dus 't gebeurt maar 1 keer, terwijl je 't anders ook constant doet voor pogingen die niet tot een oplossing leiden. Dat alleen al maakte m'n code een factor 6 (jawel !) sneller...
Hopelijk verduidelijkt dit een en ander...
Wie nog vragen/opmerkingen heeft of wie de C/C++ code zelf eens wil napluizen, mag uiteraard altijd mailen (_piranha_@pandora.be dus

) of 't hier posten...