Problema de carga | Retroceso: selección 01 (poda máxima)

Tabla de contenido

1. Comparación con el problema de carga óptima

2. Cómo elegir la carga del primer barco

3. Algoritmo de retroceso del árbol de selección

4. Optimización de la operación de poda del algoritmo de retroceso


Problema de carga: Hay n contenedores para cargar en 2 barcos con peso muerto c1 y c2 , donde el peso del contenedor i es wi y ∑wi <= c1 + c2.

Pregunte si existe un plan de carga razonable para cargar estos n contenedores en estos 2 barcos. Si es así, busque un plan de carga.

Análisis de problemas: De hecho, se puede entender como si es posible cargar todas las mercancías en el primer barco y luego en el segundo barco y dar una solución.

Lo principal a considerar es cómo instalar el primer barco. Una vez resuelto este problema, el resto se puede poner en el segundo barco. 


1. Comparación con el problema de carga óptima

Primero, echemos un vistazo a otro problema similar:

Problema de carga óptima:  hay un lote de contenedores para cargar en un barco con un peso muerto c . Donde el peso del contenedor i es el Wi . El problema de carga óptima requiere determinar que se carguen en el barco tantos contenedores como sea posible sin restricciones en el volumen de carga .

       Obviamente, el problema de carga óptima se puede resolver con avidez . Elección codiciosa: elija el recipiente con el menor peso cada vez hasta que no quepa. 

       Sin embargo, ¡el problema de carga no puede ser tan codicioso como el anterior ! Si dejamos que el primer barco cargue tantos contenedores como sea posible y utilizamos la estrategia de selección codiciosa anterior, es fácil desperdiciar espacio en el primer barco y el resultado no es óptimo. Puedes mirar el siguiente contraejemplo:


2. Cómo elegir la carga del primer barco

       Como se ha explicado anteriormente que la primera nave no puede ser codiciosa, causará una pérdida de espacio y dará como resultado resultados subóptimos. Entonces, ¿cómo se debe seleccionar la carga del primer barco?

       No es que cuanto mayor sea la cantidad de mercancías cargadas en el primer barco, mejor, pero cuanto mayor sea el peso de las mercancías cargadas en el primer barco, mejor. Es decir , el primer barco debe llenarse tanto como sea posible y toda la carga restante debe entregarse al segundo barco .

       Entonces, el proceso de realización del primer barco es en realidad un problema de  mochila DP | 01  : cada carga tiene solo dos opciones de embarque o no. Bajo la condición de que el tamaño de la mochila sea c1, elija artículos con valor y peso wi , ¡Haciendo el máximo valor posible dentro del rango de capacidad!

       Además de la programación dinámica, en realidad existe otro método, que es el algoritmo de retroceso. ¡Explícalo en detalle a continuación!


3. Algoritmo de retroceso del árbol de selección

        Veamos primero la solución de la enumeración violenta : para n elementos, enumeramos todos los números binarios de n dígitos, y si cada dígito corresponde al contenedor menor está incluido, es decir, se incluyen todos los métodos de enumeración. ¡Mientras enumera uno por uno, registre la elección que puede llenar más el barco! ( Registre el peso total bajo esta selección en cw , y mejorw registre el mayor cw en el rango de carga )

  [Tome n = 3 como ejemplo] El orden de enumeración se puede seleccionar:

  • Orden de diccionario: 000, 001, 010, 011, 100, 101, 110, 111
  • Orden inverso del sub-diccionario: opuesto al orden del diccionario
  • Secuencia de código gris: 000, 001, 011, 010, 110, 111, 101, 100 (reducir la cantidad de cálculo de cw)

       La deficiencia del algoritmo de enumeración de fuerza bruta es obvia: atraviesa muchas opciones innecesarias, pero no es fácil de podar. 


        Se puede decir que el algoritmo de retroceso es una realización racionalizada de enumeración violenta. Primero, dibuje todos nuestros esquemas de enumeración como un árbol de decisión de selección (como se muestra en la figura siguiente, la parte de la hoja es la decisión total), cada decisión corresponde a un borde del árbol y el nodo del árbol es el resultado de la selección. Entonces, la esencia del algoritmo de retroceso es buscar profundamente en este árbol ~

El proceso específico del algoritmo de retroceso se muestra en la siguiente figura, que en realidad es un simple dfs ~ 

  • Inicialización: cw = bestW = 0
  • Llamar: backstrack (1)

       Se puede encontrar que la estructura de árbol no se refleja realmente en el código. Pero la esencia de nuestra toma de decisiones se puede plasmar en un árbol, por lo que recorrer todo el código es una búsqueda profunda del árbol. ¡El algoritmo de retroceso es asombroso! El siguiente es un ejemplo para comprender todo el proceso de retroceso. Condiciones: W [16,15,15], c = 30.


La implementación de código de este algoritmo de retroceso:

int cw;  //当前重量
int bestW;  //最优重量
int c;   //船的最大承载量
int n;  //货物的数量
int w[100];   //对应 n 个集装箱的重量

/* 尽量装满第一艘船的回溯算法
 * step:层数 */
void backtrack(int step) {
    /* 到达了树叶 */
    if(step > n) {
        if(bestW < cw && cw <= c)
            bestW = cw;
        return;
    }

    cw += w[step];
    backtrack(step + 1);
    cw -= w[step];

    backtrack(step + 1);
}

4. Optimización de la operación de poda del algoritmo de retroceso

        El algoritmo de retroceso anterior no se poda, de hecho, no hay diferencia entre la complejidad general y la enumeración de fuerza bruta. A continuación, optimizamos el algoritmo de poda para el algoritmo de retroceso.


Operación de poda 1: para los subárboles que no cumplen con nuestras restricciones finales, omita el recorrido. 【Restricciones】


Operación de poda 2: para el subárbol que no puede encontrar la solución óptima, omita el recorrido. 【Condiciones limitadas】

(El pseudocódigo a continuación también agrega la matriz x para registrar elecciones específicas y mantener la solución óptima mientras se actualiza el valor óptimo)

Por lo general, las condiciones de delimitación las debemos construir nosotros mismos, por ejemplo, r se introduce para registrar.


Operación de poda 3: actualice el valor óptimo de antemano.

       Ya no solo actualice el valor óptimo en el nodo hoja, actualícelo en todos los demás nodos y regrese directamente al nodo hoja. De esta manera, el rango de poda de la condición de contorno puede ser más amplio.


Implementación de código del algoritmo de retroceso con operación de poda:

        codificación...

Supongo que te gusta

Origin blog.csdn.net/weixin_43787043/article/details/105815795
Recomendado
Clasificación