La espada se refiere a oferta89: robo de casa

Sujeto:
Un ladrón profesional planea robar casas a lo largo de la calle. Hay una cierta cantidad de efectivo escondido en cada habitación. El único factor restrictivo que afecta el robo de ladrones es que las casas adyacentes están equipadas con sistemas antirrobo interconectados. Si los ladrones entran en dos casas adyacentes en la misma noche, el El sistema emitirá una alarma automáticamente.
Dada una matriz de números enteros no negativos que representan la cantidad depositada en cada casa, calcule la cantidad máxima que se puede robar durante la noche sin activar la alarma.
Ejemplo 1:
Entrada: nums = [1,2,3,1]
Salida: 4
Explicación: Robar la casa número 1 (cantidad = 1), luego robar la casa número 3 (cantidad = 3).
Monto máximo robado = 1 + 3 = 4 .
Ejemplo 2:
Entrada: nums = [2,7,9,3,1]
Salida: 12
Explicación: Robar la casa No. 1 (cantidad = 2), robar la casa No. 3 (cantidad = 9), luego robar la casa No. 5 (cantidad = 9) = 1).
Monto máximo robado = 2 + 9 + 1 = 12 .
Análisis:
Dado que este problema no requiere enumerar todos los métodos de robo que cumplan con las condiciones del ladrón, sino que solo busca el monto máximo económico que se puede robar, es decir, encontrar la solución óptima del problema, por lo que este problema es adecuado para el uso de la programación dinámica.
La clave para usar la programación dinámica para resolver el problema es encontrar la ecuación de transición de estado Suponga que hay n casas en la calle (marcadas con 0 ~ n-1 respectivamente) y use f (i) para indicar que el ladrón comienza de la casa marcada con 0 a la casa marcada con i El valor financiero máximo que el ladrón puede robar de la casa, el valor de f(n-1) es la cantidad máxima de propiedad que el ladrón puede robar de las n casas, que es la solución del problema. El ladrón tiene dos opciones frente a la casa marcada con i. Una opción es que entre y robe algo. Como hay un sistema de alarma en la calle, no puede entrar a la casa adyacente marcada con i-1 para robar cosas, el valor máximo que puede robar antes es f(i-2), por lo que si el ladrón entra a la casa marcada con i-1, el máximo el valor financiero que puede robar es f(i-2)+nums[i].Otra opción es que el ladrón no entre a la casa marcada con i, entonces puede entrar a la casa marcada con i-1 Robando cosas adentro, entonces la cantidad máxima de dinero que puede robar en este momento es f(i-1), entonces la cantidad máxima de dinero que el ladrón puede robar cuando llega a la casa marcada con i es el valor máximo de las dos opciones, es decir, f(i)=max (f(i-2)+nums[i],f(i-1)).
La ecuación de transición de estado anterior tiene una condición implícita, asumiendo que i es mayor o igual a 2. Cuando i es igual a 0, f(0) es la cantidad máxima de dinero que un ladrón puede robar cuando solo hay una casa etiquetada 0 en la calle, f( 1)=max(nums[0],nums[1]).
Para evitar la duplicación innecesaria de cálculos, se puede crear un arreglo dp cuyo i-ésimo elemento dp[i] se usa para contener el resultado de f(i). Si el resultado de f(i) se calculó antes, simplemente lea el valor de dp[i] de la matriz dp y el cálculo no se puede repetir.
Otra forma de pensar:
use dos ecuaciones de transición de estado para analizar y resolver el problema, f(i) representa la cantidad financiera máxima que el ladrón puede robar cuando elige no entrar a la casa marcada con i para robar, y g(i) representa el ladrón elige ingresar la etiqueta La cantidad máxima de dinero que se puede robar al robar para la casa de i.
f(i)=max(f(i-1),g(i-1)),
g(i)=f(i-1)+nums[i].
Y estas dos expresiones implican la condición i>0, de lo contrario i-1 no tiene significado f(0)=0.g(0)=nums[0]
inserte la descripción de la imagen aquí

Código:

import javax.crypto.spec.PSource;
import java.util.Arrays;

public class Rob {
    
    
    public int rob(int[] nums) {
    
    
        if (nums.length == 0){
    
    
            return 0;
        }
        int[] dp = new int[nums.length];
        //填充数组,将数组中的值都设置为-1
        Arrays.fill(dp,-1);
        helper(nums,nums.length-1,dp);
        return dp[nums.length-1];
    }

    private void helper(int[] nums, int i, int[] dp) {
    
    
        if (i == 0){
    
    
            dp[i] = nums[0];
        }else if (i == 1){
    
    
            dp[i] = Math.max(nums[0],nums[1]);
        }else if (dp[i] < 0){
    
    
            helper(nums,i-2,dp);
            helper(nums,i-1,dp);
            dp[i] = Math.max(dp[i-1],dp[i-2]+nums[i]);
        }
    }
    //换一种思路:先求出f(0)和f(1)的值,然后用f(0),f(1)的值求出f(2),用f(1)和f(2)的值求出f(3),以此类推,直至求出f(n-1)。用for循环来完
    //成这个自下而上的思路。
    public int rob1(int[] nums){
    
    
        if (nums.length == 0){
    
    
            return 0;
        }
        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        if (nums.length > 1){
    
    
            dp[1] = Math.max(nums[0],nums[1]);
        }
        for (int i = 2; i < nums.length; i++) {
    
    
            dp[i] = Math.max(dp[i-1],dp[i-2] + nums[i]);
        }
        return dp[nums.length - 1];
    }
    //空间复杂度为O(1)的迭代代码
    public int rob2(int[] nums){
    
    
        if (nums.length == 0){
    
    
            return 0;
        }
        //dp[i]只需缓存两个值就足够了,并不需要一个长度为n的数组,因此可以进一步优化代码的空间效率。
        int[] dp = new int[2];
        dp[0] = nums[0];
        if (nums.length > 1){
    
    
            dp[1] = Math.max(nums[0],nums[1]);
        }
        //可以根据f(i-1)和f(i-2)的结果计算出f(i),然后用f(i)的结果写入数组原来保存f(i-2)的结果的位置。接下来用f(i-1)和f(i)的结果计算f(i+1),f(i-2)的值虽然会被覆盖,但以后再也不会用到这个值,因此不会带来任何问题。
        for (int i = 2; i < nums.length; i++) {
    
    
            dp[i%2] = Math.max(dp[(i-1)%2],dp[(i-2)%2] + nums[i]);
        }
        return dp[(nums.length-1)%2];
    }
    //    用两个状态转移方程分析解决问题
    public int rob3(int[] nums){
    
    
        int len = nums.length;
        if (len == 0){
    
    
            return 0;
        }
        int[][] dp = new int[2][2];
        dp[0][0] = 0;
        dp[1][0] = nums[0];
        for (int i = 1; i < len; i++) {
    
    
            dp[0][i%2] = Math.max(dp[0][(i-1)%2],dp[1][(i-1)%2]);
            dp[1][i%2] = dp[0][(i-1)%2]+nums[i];
        }
        return Math.max(dp[0][(len-1)%2],dp[1][(len-1)%2]);
    }
}

inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/Jiaodaqiaobiluo/article/details/122886910
Recomendado
Clasificación