vivan esas clases de algoritmica!! estaba claro que era bactracking... lo unico una duda: para que usas el 0? simplemente no hace falta tenerlo en cuenta a la hora de hacer los calculos, ya que no conoce el 0 ni ninguno más allá del 5
EDITO: Voy a probar otro punto de vista. Mezcla de voraces y bactracking. Simplemente es ir cogiendo los numeros en orden (1,2,3,4,5) e ir añadiendo el numero actual a la suma, hasta que llegue al numero o me pase, momento en el que doy un paso atras en recursividad y cojo el siguiente:
por ejemplo para 3 sería
1
11
111 /* Es 3 luego paro y vuelvo atras */
112 /* Me he pasado, lo descarto y vuelvo atras */
12 /* Es 3 me vale, vuelvo atras */
121 /* Me he pasado, para atrás */
2
21 /* Me vale */
ad infinitum xD
EDITO LO EDITADO: He terminado mi algoritmo. Aquí pongo todo el código. He añadido lo de david para comparar llamadas recursivas y tiempo de ejecución.
En cuanto a diferencias, el tuyo está mejor porque no dependes de variables externas, a diferencia del mío.
- Código: Seleccionar todo
- #include <vector>
 #include <iostream>
 #include <time.h>
 
 typedef std::vector<int> Vi;
 
 int valores[4] = {1,1,2,3};
 int numeros_conocidos[4] = {1,4,2,3};
 
 void numeros_gustavo(int& iteraciones,int& numeros, int numero_a_calcular, Vi& numeros_usados, int& suma)
 {
 int pos_actual = 0;
 while(pos_actual < 4 && suma + valores[pos_actual] <= numero_a_calcular)
 {
 
 // Anotar
 numeros_usados.push_back(numeros_conocidos[pos_actual]);
 suma += valores[pos_actual];
 
 numeros_gustavo(++iteraciones,numeros,numero_a_calcular, numeros_usados, suma);
 
 //Desanotar
 suma -= valores[pos_actual];
 numeros_usados.pop_back();
 pos_actual++;
 }
 if (suma == numero_a_calcular)
 {
 numeros++;
 pos_actual = 4;
 }
 }
 
 const int DigsGus[]= {0,1,1,2,3};
 const int NDigGus = 5;
 
 bool suma_n(const Vi& v, int n) {
 int suma = 0;
 for (int i = 0; i < v.size(); i++) {
 suma += v[i];
 }
 return suma == n;
 }
 
 int numerosGus(int& iteraciones, Vi& v, int i, int n) {
 if (i == n) {
 return suma_n(v, n);
 }
 int nums = 0;
 int j = 0;
 if (v[std::max(i-1,0)] != 0) ++j;
 while (j < NDigGus) {
 v[i] = DigsGus[j];
 nums += numerosGus(++iteraciones,v, i+1, n);
 ++j;
 }
 return nums;
 }
 
 
 int main(int argc, char* argv[])
 {
 int numero_a_calcular;
 time_t tiempo, differ;
 while( std::cin >> numero_a_calcular)
 {
 int numeros = 0, numeros2 = 0;
 
 int suma_acumulada = 0;
 int iteraciones = 0, iteraciones2 = 0;
 
 Vi numeros_usados, numeros_usados2(numero_a_calcular, 0);
 numeros_usados.reserve(numero_a_calcular + 10);
 
 
 tiempo = time(NULL);
 numeros_gustavo(iteraciones,numeros, numero_a_calcular, numeros_usados, suma_acumulada );
 differ = time(NULL) - tiempo;
 std::cout << "ITERACIONES Juan: " << iteraciones << " NUMEROS: " << numeros <<
 " TIEMPO: " << differ << std::endl;
 
 tiempo = time(NULL);
 numeros2 = numerosGus(iteraciones2, numeros_usados2, 0, numero_a_calcular);
 differ = time(NULL) - tiempo;
 std::cout << "ITERACIONES David: "<< iteraciones2 <<  " NUMEROS: " << numeros2 <<
 " TIEMPO: " << differ << std::endl;
 }
 }