Recursión violenta a la programación dinámica (3)

En los dos primeros artículos sobre la conversión de la recursividad violenta en programación dinámica, el problema se resolvió mediante un enfoque de arriba hacia abajo. Este artículo convertirá la recursividad violenta en programación dinámica atravesando la matriz de izquierda a derecha.

Hay
dos matrices de igual longitud w [] y v [], w [i] y v [i] representan el peso y el valor del artículo i respectivamente. Dada una bolsa entera positiva, representa la capacidad de carga de la mochila y la mercancía cargada no puede exceder la capacidad de carga de la mochila ¿Cuál es el valor máximo que puedes llevar a cambio?

Recursividad violenta
El punto clave de la recursividad violenta es probar, lo que pruebas es lo que obtienes: primero prueba el método de recursividad violenta y luego conviértelo en programación dinámica de acuerdo con el método de recursividad violenta.
La idea general del método es la siguiente: independientemente de los productos anteriores, comience desde el número de índice de los productos, concéntrese solo en el índice y los productos posteriores, si desea los productos actuales, use el peso de la mochila: los productos actuales. peso y obtenga el valor actual de los bienes, si no desea los bienes actuales, simplemente baje el índice directamente.

Código
El método principal llama al proceso. Según el análisis anterior, si el método del proceso puede devolver el valor máximo de acuerdo con los parámetros pasados, se completa el método recursivo violento.

public static int maxValue(int[] w, int[] v, int bag) {
    
    
		//边界判断,如果v w满足以下条件,说明是无用参数,返回0
        if (w == null || v == null || w.length != v.length || w.length == 0 || v.length == 0) {
    
    
            return 0;
        }
		
        return process(w, v, bag, 0);
    }

A continuación, mejore el método del proceso.
Entre ellos, hay algunos pequeños defectos a juzgar por las condiciones de contorno de la bolsa, como la parte del comentario:

  1. ¿Por qué la bolsa solo puede ser menor que 0? Porque, si el peso de la bolsa es exactamente 0 después de adquirir el artículo actual y el peso del siguiente artículo es 0, pero el valor es enorme, ¿quieres conseguirlo? Deberia estar disponible. Entonces bolsa < 0.
  2. Después de bolsa <0, ¿por qué se devuelve -1 en lugar de 0? Porque, si mi carga actual es la última, la siguiente irá a índice = v.length, y devolverá 0, pero si tengo sobrepeso en este momento, y si bolsa < 0, también devolverá 0, es ¿Qué información se devuelve recursivamente al flujo ascendente? También use el valor de los bienes actuales + este 0, pero los bienes en este momento no deben empacarse en una mochila, por lo que devuelve -1, y primero llame a siguiente para ver el valor de retorno del Productos actuales para juzgar.
  //不考虑之前的,从index出发,看是否要当前货物
    private static int process(int[] w, int[] v, int bag, int index) {
    
    
	     /* if (bag <= 0){
	            return 0;
	        }
	        
	        if (bag < 0){
	            return 0;
	        }
		int p2 = v[index] + process(w, v, bag - w[index], index + 1);
		*/
        if (bag < 0) {
    
    
            return -1;
        }
		//当前位置来到了数组长度位置,说明没货物了,return 0。
        if (index == v.length) {
    
    
            return 0;
        }

        //如果不要当前货物,则背包重量无变化,去下一个货物
        int p1 = process(w, v, bag, index + 1);
        //如果要当前货物,则背包重量 - 货物重量,并且 + 当前货物价值。
        int p2 = 0;
        //此处需要先判断,当前货物要完后,背包是否超重,所以先获取next的返回值
        int next = process(w, v, bag - w[index], index + 1);
        if (next != -1) {
    
    
            p2 = v[index] + next;
        }
        return Math.max(p1, p2);
    }

En este punto se ha completado el método de recursividad violenta, veamos si se convierte en programación dinámica. Como dije antes, una de las cosas más importantes acerca de la recursividad violenta a la programación dinámica esSegún los parámetros variables, ver si hay alguna solución repetida en el subproceso.. En este momento, se puede ver dando un ejemplo práctico para enumerar el proceso de llamada.
En el código nuestros parámetros variables son el resto, peso e índice de la bolsa, se puede ver en el ejemplo que hay soluciones repetidas, bueno, entonces comenzamos a cambiar la programación dinámica de acuerdo con el código recursivo violento.
inserte la descripción de la imagen aquí

Programación dinámica
Según el análisis anterior, se han encontrado parámetros variables (índice [fila] y capacidad restante de la mochila [columna]). Determine el tamaño de la tabla de caché dp de acuerdo con los parámetros variables y cree la tabla de caché dp.
Y según el código recursivo violento se puede analizar que:

  1. El índice es la posición de longitud de la matriz alcanzable.
  2. La capacidad restante de la mochila también comienza desde llena, por lo que también se puede alcanzar la posición de longitud del conjunto.

Se puede analizar según el caso base recursivo violento y la relación de llamada.

  1. Cuando index == v.length devuelve 0, por lo que el valor de la última fila de la tabla dp es 0.
  2. Independientemente de si se van a buscar los bienes actuales o no, cada llamada al método de proceso toma el índice + 1, por lo que todo el proceso de dependencia es que la línea anterior depende de la línea siguiente.

¿Cómo llenar la tabla dp después de obtenerla? ¡Simplemente reescriba el código de acuerdo con la recursividad violenta! ! ! El valor a obtener es el valor máximo de la mochila comenzando desde 0, por lo que basta con obtener el número de posición de dp[0][bolsa].

     //根据可变参数,确定dp表范围
    //N:可到达N ,所以是0 ~ N +1
    //bag: 可到达bag  -1 ~ bag + 1
    public static int maxValue2(int[] w, int[] v, int bag) {
    
    
        if (w == null || v == null || w.length != v.length || w.length == 0 || v.length == 0) {
    
    
            return 0;
        }
        int N = v.length;
        //数组初始化都是0,所以不用对dp表最后的行进行循环赋值操作
        int[][] dp = new int[N + 1][bag + 1];
		//因为是后面行依赖前面行,所以从最后行开始向前遍历
        for (int index = N - 1 ; index >= 0; index--) {
    
    
        	//填充bag剩余容量rest
            for (int rest = 0; rest <= bag; rest++) {
    
    
                int p1 = dp[index +1][rest];
                int p2 = 0;
                int next = rest - w[index] < 0 ? -1 : dp[index + 1][rest - w[index]];
                if (next != -1){
    
    
                    p2 = v[index] + next;
                }
                dp[index][rest] = Math.max(p1,p2);
            }
        }
        return dp[0][bag];
    }

Supongo que te gusta

Origin blog.csdn.net/weixin_43936962/article/details/132603953
Recomendado
Clasificación