Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] recursividad c++ hallar todas las posibles soluciones de la suma de un vecto

Estas en el tema de recursividad c++ hallar todas las posibles soluciones de la suma de un vecto en el foro de C/C++ en Foros del Web. Buenas noches comunidad , tengo un problema con este ejercicio de recursividad , la vdd no se me da muy bien este temam el ejercicio ...
  #1 (permalink)  
Antiguo 02/05/2016, 21:29
 
Fecha de Ingreso: mayo-2016
Mensajes: 6
Antigüedad: 7 años, 11 meses
Puntos: 0
recursividad c++ hallar todas las posibles soluciones de la suma de un vecto

Buenas noches comunidad , tengo un problema con este ejercicio de recursividad , la vdd no se me da muy bien este temam el ejercicio consiste en hallar todas las posibles soluciones de la suma de un vector que tengan como resultado un numero n ejemplo
Ejm: Si V: 8, 2, 3, 3, 6, 4. y X=13
Soluciones:
3+6+4 = 13
8+2+3=13

este es el codigo que eh hecho hasta ahora pero solo estoy tirando flechas :/

Código:
#include<iostream>

using namespace std;


int sumar(int V[6]){
    int acumulado = 0;
    int longitud_vector = 6;
    for( int i=0; i<longitud_vector; i++){  
        acumulado += V[i];
    }    
    return acumulado;
}

void imprimir(int sol[6]){
    cout<<"Solucion"<<endl;
    int longitud_vector = 6;
    for( int i=0; i<longitud_vector; i++){  
        if(sol[i] != 0){
            cout<<sol[i]<<" + ";
        }
    }
    
}

void imprimir_disp(bool disp[6]){
    
    int longitud_vector = 6;
    for( int i=0; i<longitud_vector; i++){  
        if(disp[i] == true){
            cout<<1<<" ";
        }else{
            cout<<0<<" ";    
        }
    }
    cout<<endl;
        
}

void imprimir_sol(int sol[6]){
    
    int longitud_vector = 6;
    for( int i=0; i<longitud_vector; i++){  

        cout<<sol[i]<<" ";
    }
    cout<<endl;
        
}

void vaciar_vector_sol(int sol[6]){
    int longitud_vector = 6;
    for( int i=0; i<longitud_vector; i++){  
        sol[i] = 0;
    }    
}

void reiniciar_disp(bool disp[6]){
    int longitud_vector = 6;
    for( int i=0; i<longitud_vector; i++){  
        disp[i] = true;
    }    
}

void suma2 (int V[6], int obj, bool disp[6] , int sol[6] ,int etapa) {

    
    int longitud_vector = 6;

    
    for( int i=0; i<longitud_vector; i++){  

        if( (disp[i]==true) && ( (sumar(sol)+V[i]) <= obj) ) {
            disp[i] = false;
            sol[i] = V[i];
        
        
            /*Si la suma de los elementos del vector de 
              solucion es igual a el resultado buscado */     
            if (sumar(sol) == obj ){
                cout<<"\n=>";
                imprimir(sol);
           
            }else{ //si no, se hace un llamado recursivo de la funcion para buscar esa solucion

                suma2(V,obj,disp,sol,etapa+1);

            }
      
        }

         
    }

}

void suma(int Vector[6], int x)
{
    bool Disponibles[6];
    int Solucion[6] ,i;
    int longitud_vector = 6;
    
    //cambio todas las pocisiones del vector ah verdadero

    for(i=0; i<longitud_vector; i++){
        Disponibles[i] = true;
        Solucion[i] = 0;
    }
        
    suma2(Vector,x,Disponibles, Solucion, 0);
}




int main(){
    int Vector[6] = {8,2,3,3,6,4}; //vector
    //int Vector[6] = {6,4,3,3,5,3}; //vector
    int longitud_vector = 6;
    //cout<<"hola "<<longitud_vector<<endl;
    suma(Vector,13);
    system("pause");
    return 0;    
}
de verdad muchas gracias de antemano y espero puedan ayudarme
  #2 (permalink)  
Antiguo 03/05/2016, 02:45
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: recursividad c++ hallar todas las posibles soluciones de la suma de un ve

¿Seguro que este problema tienes que resolverlo con recursividad?

Yo sinceramente creo que con bucles la solución es mucho más sencilla.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #3 (permalink)  
Antiguo 03/05/2016, 03:29
 
Fecha de Ingreso: mayo-2016
Mensajes: 6
Antigüedad: 7 años, 11 meses
Puntos: 0
Respuesta: recursividad c++ hallar todas las posibles soluciones de la suma de un ve

en realidad con bucles es muy facil de resolver , pero una de las condiciones es que debe ser recursivo , hay esta el rollo del asunto
  #4 (permalink)  
Antiguo 03/05/2016, 03:53
Avatar de Malenko
Moderador
 
Fecha de Ingreso: enero-2008
Mensajes: 5.323
Antigüedad: 16 años, 3 meses
Puntos: 606
Respuesta: recursividad c++ hallar todas las posibles soluciones de la suma de un ve

una vez que lo tienes con bucles, pasarlo a recursivo es sencillo. Lo mismo al revés. Es meramente un proceso mecánico.
__________________
Aviso: No se resuelven dudas por MP!
  #5 (permalink)  
Antiguo 03/05/2016, 03:56
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: recursividad c++ hallar todas las posibles soluciones de la suma de un ve

Yo este problema lo solucionaría un poco con ayuda de contenedores, ya que una secuencia de elementos puede tener un número indeterminado de posibles soluciones, cada una de ellas con un número indeterminado de elementos (eso sí, num de elementos de la solucion <= num de elementos del vector).

La desventaja de usar, como es tu caso, un vector de bool es que el reinicio de los valores has de realizarlo con sumo cuidado si no quieres acabar mal parado.

El caso es que si cada llamada recursiva recibe un vector de elementos (la combinación que se está comprobando actualmente) es sencillo realizar todas las combinatorias.

Entonces, la función recursiva podría tener esta firma:

Código C++:
Ver original
  1. typedef std::vector<int> Items;
  2. typedef std::vector<Items> Resultado;
  3.  
  4. Resultado suma( int* ptr, int totalBuscado, int contadorValoresRestantes, Items parcial);

Donde:
  • ptr apunta al elemento actual del vector
  • totalBuscado indica la suma que debemos localizar
  • contadorValoresRestantes indica cuántos elementos quedan por procesar del vector
  • parcial almacena la secuencia que estamos comprobando actualmente

Dado que lo que estamos pasando de forma recursiva es una combinación de elementos, parece buena idea usar una función de ayuda que sume los elementos de dicha combinación. Aunque sea una chorrada de función, mejor separar las cosas por claridad:

Código C++:
Ver original
  1. int suma(const Items& items)
  2. {
  3.   return std::accumulate(items.begin(),items.end(),0);
  4. }

Volviendo a la función recursiva, lo que hay que hacer es probar todas las combinaciones posibles, luego cada iteración tiene que probar las combinaciones con el número actual y sin el (en el ejemplo que has puesto, los resultados válidos pueden o no incorporar el primer elemento del vector, el 8). En el caso de que añada el número a la combinación basta con actualizar parcial.

Además, sabemos que si el parcial es superior al número buscado hay que abortar esa combinación puesto que sumar más valores no va a ayudar a encontrar un resultado bueno.

Con esto la función podría quedar así:

Código C++:
Ver original
  1. Resultado suma( int* ptr, int totalBuscado, int contadorValoresRestantes, Items parcial)
  2. {
  3.     Resultado resultado;
  4.  
  5.     contadorValoresRestantes--;
  6.     if( contadorValoresRestantes >= 0 )
  7.     {
  8.         // Probamos sin añadir el elemento actual
  9.         resultado = suma((ptr+1),totalBuscado,contadorValoresRestantes,parcial);
  10.     }
  11.  
  12.     // Probamos añadiendo el elemento actual
  13.     parcial.push_back(*ptr);
  14.     int total = suma(parcial);
  15.     if( (total < totalBuscado) && (contadorValoresRestantes >= 0) )
  16.     {
  17.         Resultado resultado2 = suma(++ptr,totalBuscado,contadorValoresRestantes,parcial);
  18.  
  19.         // Hay que fusionar ambos resultados
  20.         // Esta línea básicamente copia el contenido de resultado2 al final de resultado
  21.         resultado.insert(resultado.end(),resultado2.begin(),resultado2.end());
  22.     }
  23.     else if( total == totalBuscado )
  24.     {
  25.         // Si hemos encontrado una solución, la añadimos al resultado
  26.         resultado.push_back(parcial);
  27.     }
  28.  
  29.     return resultado;
  30. }

Ya está la función recursiva terminada.

Para simplificar su uso se puede hacer una función que haga las veces de entrada al algoritmo... quizás algo así:

Código C++:
Ver original
  1. Resultado suma( int* ptr, int numeroValores, int totalBuscado)
  2. {
  3.     return suma(ptr,totalBuscado,numeroValores-1,std::vector<int>());
  4. }

Y bueno, vamos a probar el código:

Código C++:
Ver original
  1. int main()
  2. {
  3.   const int SIZE = 6;
  4.   int Vector[SIZE] = {8,2,3,3,6,4}; //vector
  5.   Resultado resultados = suma(Vector,SIZE,13);
  6.  
  7.   std::cout << "Resultados: " << std::endl;
  8.   if( !resultados.empty() )
  9.   {
  10.     auto lambda = [&](const std::vector<int>& items)
  11.     {
  12.       std::string separador;
  13.       std::for_each(items.begin(),items.end(),[&](int v){ std::cout << separador << v; separador = ","; });
  14.       std::cout << std::endl;
  15.     };
  16.    
  17.     std::for_each(resultados.begin(),resultados.end(),lambda);
  18.   }
  19.   else
  20.     std::cout << "No hay resultados!!!" << std::endl;
  21. }

Lo que ofrece el siguiente resultado:

Código:
Resultados:
3,6,4
3,6,4
8,2,3
8,2,3
Vaya, los resultados aparecen duplicados. ¿Es un error? En absoluto. Lo que pasa es que hay dos elementos con valor 3, lo que arroja dos resultados distintos. Si quieres eliminar esos duplicados puedes optar por soluciones un poco más sofisticadas, una posibilidad es usar el contenedor set, pero eso tendrás que investigarlo un poco antes de que te ponga una respuesta :)

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #6 (permalink)  
Antiguo 03/05/2016, 05:34
 
Fecha de Ingreso: abril-2016
Mensajes: 31
Antigüedad: 8 años
Puntos: 5
Respuesta: recursividad c++ hallar todas las posibles soluciones de la suma de un ve

Hola; tengo otra versión, casi tan espantosa como la de arriba :)

Código C++:
Ver original
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <set>
  5.  
  6. using sstype = std::set<std::set<int>>;
  7.  
  8. sstype& permutar(std::vector<int> p, std::vector<int> f, int suma)
  9. {
  10.     static sstype ss;
  11.  
  12.     if(suma == std::accumulate(p.begin(), p.end(), 0)) {
  13.         ss.emplace(std::set<int>(p.begin(), p.end()));
  14.         return ss;
  15.     }
  16.  
  17.     for(size_t i = 0; i < f.size(); ++i) {
  18.         auto ppio = p;
  19.         ppio.push_back(f[i]);
  20.         auto fin = f;
  21.         fin.erase(fin.begin() + i);
  22.  
  23.         permutar(ppio, fin, suma);
  24.     }
  25.  
  26.     return ss;
  27. }
  28.  
  29. int main()
  30. {
  31.     std::vector<int> v{8, 2, 3, 3, 6, 4};
  32.     const int suma = 13;
  33.  
  34.     auto ss = permutar(std::vector<int>{}, v, suma);
  35.  
  36.     for(auto& i : ss) {
  37.         for(auto& j : i)
  38.             std::cout << j << ' ';
  39.         std::cout << '\n';
  40.     }
  41. }

Última edición por enrieto; 03/05/2016 a las 05:53
  #7 (permalink)  
Antiguo 03/05/2016, 06:35
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: recursividad c++ hallar todas las posibles soluciones de la suma de un ve

Cita:
Iniciado por enrieto Ver Mensaje
Hola; tengo otra versión, casi tan espantosa como la de arriba :)
En lo referente a la respuesta de arriba... hay una opción para que los mensajes más recientes aparezcan los primeros (yo la tengo activada) luego en ese caso tu respuesta estará encima de la mía :P

Y por cierto, tu respuesta no la calificaría como espantosa. Más bien sería original.

La única pega es que va a dar resultados incorrectos si la secuencia tiene números repetidos (efecto secundario del set):

Entrada:
Código C++:
Ver original
  1. std::vector<int> v{8, 2, 3, 3, 6, 4};
  2.     const int suma = 6;

Salida:
Código:
2 4 
3 
6
Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #8 (permalink)  
Antiguo 03/05/2016, 07:10
 
Fecha de Ingreso: abril-2016
Mensajes: 31
Antigüedad: 8 años
Puntos: 5
Respuesta: recursividad c++ hallar todas las posibles soluciones de la suma de un ve

[Edito], y si queda algo pasa para la versión beta.

Código C++:
Ver original
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <set>
  5.  
  6. struct cmp {
  7.     bool operator() (std::vector<int> a, std::vector<int> b)
  8.     {
  9.         std::sort(a.begin(), a.end());
  10.         std::sort(b.begin(), b.end());
  11.         return a < b;
  12.     }
  13. };
  14.  
  15. typedef std::set<std::vector<int>, cmp> sstype;
  16.  
  17. sstype& permutar(std::vector<int> p, std::vector<int> f, int suma)
  18. {
  19.     static sstype ss;
  20.  
  21.     if(suma == std::accumulate(p.begin(), p.end(), 0)) {
  22.         ss.emplace(p.begin(), p.end());
  23.         return ss;
  24.     }
  25.  
  26.     for(size_t i = 0; i < f.size(); ++i) {
  27.         auto ppio = p;
  28.         ppio.push_back(f[i]);
  29.         auto fin = f;
  30.         fin.erase(fin.begin() + i);
  31.  
  32.         permutar(ppio, fin, suma);
  33.     }
  34.  
  35.     return ss;
  36. }
  37.  
  38. int main()
  39. {
  40.     std::vector<int> v{8, 2, 3, 3, 6, 4};
  41.     const int suma = 6;
  42.  
  43.     auto ss = permutar(std::vector<int>{}, v, suma);
  44.  
  45.     for(auto& i : ss) {
  46.         for(auto& j : i)
  47.             std::cout << j << ' ';
  48.         std::cout << '\n';
  49.     }
  50. }
  #9 (permalink)  
Antiguo 03/05/2016, 07:18
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: recursividad c++ hallar todas las posibles soluciones de la suma de un ve

Cita:
Iniciado por enrieto Ver Mensaje
[Edito], y si queda algo pasa para la versión beta.
Yo creo que así ya cumple perfectamente con su cometido
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #10 (permalink)  
Antiguo 03/05/2016, 18:42
 
Fecha de Ingreso: mayo-2016
Mensajes: 6
Antigüedad: 7 años, 11 meses
Puntos: 0
Respuesta: recursividad c++ hallar todas las posibles soluciones de la suma de un ve

Buenas noches eh tenido problemas para compilar sus codigos la verdad me enrede bastante con unas cosas que no entiendo , voy a documentarme mejor ya que se ven interesante , de todas formas estoy escribiendo para que no crean que me fugue con la solucion xD , si siquiera decir gracias , muchas gracias de antemano y cuando logre correr el codigo les comento ,(soy nuevo en esto de los foros asi que paciencia por favor)

Saludos!!!
  #11 (permalink)  
Antiguo 04/05/2016, 10:03
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: recursividad c++ hallar todas las posibles soluciones de la suma de un ve

Se me ocurre algo y no se si seria una locura. Pide que encuentre todas las combinaciones posibles donde se de una condición y se me ocurre que se podría obtener todas las permutaciones posibles y en cada una usa dos bucles donde se va probando si la suma sirve, o sea que sumas el primero con el siguiente y el siguiente... hasta que de él número buscado o hasta que te pases y después haces lo mismo pero empezando desde el segundo y así hasta el final y luego haces una permuta y repites y así hasta realizar todas las permutaciones posibles. Por supuesto habría que desechar las combinaciones que se repitan. ¿Seria buena idea o seria complicarse la vida?
En este código se usa recursividad para permutaciones:
Código C:
Ver original
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. /* print a list of ints */
  5. int show(int *x, int len)
  6. {
  7.     int i;
  8.     for (i = 0; i < len; i++)
  9.         printf("%d%c", x[i], i == len - 1 ? '\n' : ' ');
  10.     return 1;
  11. }
  12.  
  13. /* next lexicographical permutation */
  14. int next_lex_perm(int *a, int n) {
  15. #   define swap(i, j) {t = a[i]; a[i] = a[j]; a[j] = t;}
  16.     int k, l, t;
  17.  
  18.     /* 1. Find the largest index k such that a[k] < a[k + 1]. If no such
  19.           index exists, the permutation is the last permutation. */
  20.     for (k = n - 1; k && a[k - 1] >= a[k]; k--);
  21.     if (!k--) return 0;
  22.  
  23.     /* 2. Find the largest index l such that a[k] < a[l]. Since k + 1 is
  24.        such an index, l is well defined */
  25.     for (l = n - 1; a[l] <= a[k]; l--);
  26.  
  27.     /* 3. Swap a[k] with a[l] */
  28.     swap(k, l);
  29.  
  30.     /* 4. Reverse the sequence from a[k + 1] to the end */
  31.     for (k++, l = n - 1; l > k; l--, k++)
  32.         swap(k, l);
  33.     return 1;
  34. #   undef swap
  35. }
  36.  
  37. void perm1(int *x, int n, int callback(int *, int))
  38. {
  39.     do {
  40.         if (callback) callback(x, n);
  41.     } while (next_lex_perm(x, n));
  42. }
  43.  
  44. /* Boothroyd method; exactly N! swaps, about as fast as it gets */
  45. void boothroyd(int *x, int n, int nn, int callback(int *, int))
  46. {
  47.     int c = 0, i, t;
  48.     while (1) {
  49.         if (n > 2) boothroyd(x, n - 1, nn, callback);
  50.         if (c >= n - 1) return;
  51.  
  52.         i = (n & 1) ? 0 : c;
  53.         c++;
  54.         t = x[n - 1], x[n - 1] = x[i], x[i] = t;
  55.         if (callback) callback(x, nn);
  56.     }
  57. }
  58.  
  59. /* entry for Boothroyd method */
  60. void perm2(int *x, int n, int callback(int*, int))
  61. {
  62.     if (callback) callback(x, n);
  63.     boothroyd(x, n, n, callback);
  64. }
  65.  
  66. /* same as perm2, but flattened recursions into iterations */
  67. void perm3(int *x, int n, int callback(int*, int))
  68. {
  69.     /* calloc isn't strictly necessary, int c[32] would suffice
  70.        for most practical purposes */
  71.     int d, i, t, *c = calloc(n, sizeof(int));
  72.  
  73.     /* curiously, with GCC 4.6.1 -O3, removing next line makes
  74.        it ~25% slower */
  75.     if (callback) callback(x, n);
  76.     for (d = 1; ; c[d]++) {
  77.         while (d > 1) c[--d] = 0;
  78.         while (c[d] >= d)
  79.             if (++d >= n) goto done;
  80.  
  81.         t = x[ i = (d & 1) ? c[d] : 0 ], x[i] = x[d], x[d] = t;
  82.         if (callback) callback(x, n);
  83.     }
  84. done:   free(c);
  85. }
  86.  
  87. #define N 4
  88.  
  89. int main()
  90. {
  91.     int i, x[N];
  92.     for (i = 0; i < N; i++) x[i] = i + 1;
  93.  
  94.     /* three different methods */
  95.     perm1(x, N, show);
  96.     perm2(x, N, show);
  97.     perm3(x, N, show);
  98.  
  99.     return 0;
  100. }
Lo saqué de esta página donde lo hay en otros lenguajes: http://rosettacode.org/wiki/Permutations#C.2B.2B

Última edición por aguml; 04/05/2016 a las 10:13

Etiquetas: ayuda!!, c++, ejercicios, recursividad
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 15:34.