La espada se refiere a oferta88: el menor costo de subir escaleras

Pregunta:
Cada subíndice de la matriz se usa como un paso, y el i-ésimo paso corresponde a un valor de costo físico no negativo cost[i] (el subíndice comienza desde 0).
Cada vez que suba una escalera, gastará el valor de resistencia correspondiente. Una vez que haya pagado el valor de resistencia correspondiente, puede elegir subir una escalera o dos escaleras.
Encuentre el costo mínimo para llegar a la parte superior del piso. Al principio, puede elegir el elemento del índice 0 o 1 como la escalera inicial.
1.
Entrada: costo = [10, 15, 20]
Salida: 15
Explicación: El costo mínimo comienza desde el costo [1] y luego toma dos pasos hasta la parte superior de la escalera, que cuesta 15 en total.
2.
Entrada: costo = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
Salida: 6
Explicación: El método de costo más bajo es comenzar desde el costo [0], pasar por esos 1 por uno, skip cost[3] , que cuesta 6 en total.
Análisis:
cada vez que subes esta pregunta, puedes subir un escalón o dos escalones, lo que significa que hay dos opciones para cada escalón. Parece que esto está relacionado con el backtracking, pero el problema no es averiguar de cuántas maneras hay que subir las escaleras, sino calcular el costo mínimo de subir las escaleras, es decir, calcular la solución óptima al problema, por lo que este problema es más adecuado para la programación dinámica.
Para el método de programación dinámica, primero debemos determinar la ecuación de transición de estado, que se puede expresar como f(i) para representar el costo mínimo de subir desde el i-ésimo escalón de las escaleras. Si una escalera tiene n escalones (escalones de 0 a n-1), dado que se pueden subir 1 o 2 escalones a la vez, es posible subir desde los escalones n-2 o n-1 hasta la parte superior de las escaleras, el mínimo de f(n-1) y f(n-2), es la solución óptima a este problema. El coste mínimo de subir desde el i-ésimo escalón debe ser el menor entre el coste mínimo de subir desde el i-1er escalón y el coste mínimo de subir desde el i-2º escalón más El coste de i escalones = "f( i)=min(f(i-1),f(i-2))+cos[i]. Esta ecuación tiene una condición implícita, es decir, i es mayor o igual a 2. Si i es igual a 0, puedes subir directamente desde el escalón 0. f(0)=cos[0], si i es igual a 1, se menciona en el título que puedes subir desde el primer escalón, entonces f(1)=cos[1].
Hay cuatro soluciones a este problema: el
círculo 9 representa f(9). La primera solución parece tener un código simple, pero la complejidad del tiempo es muy mala. Por ejemplo, f(6) necesita calcularse muchas veces. De hecho , solo un cálculo es suficiente Otros Los cálculos son redundantes, por lo que necesitamos una operación de poda, que es la segunda solución, para evitar cálculos repetidos y usar una matriz para almacenar los resultados.
O podemos resolver este proceso de abajo hacia arriba de una manera diferente, es decir, comenzar con los subproblemas y encontrar el resultado de f(i) en función de las soluciones de los dos subproblemas f(i-1) yf(i-2). La cuarta idea es optimizar sobre la base de la tercera idea, principalmente para reducir la complejidad del espacio.En el frente, se usa una matriz de longitud n para guardar todos los resultados de f(i) y resolver el problema de f(i ) Los resultados se guardan. Sin embargo, al resolver f(i), solo se necesitan los resultados de f(i-1) y f(i-2) Los resultados de 0 a f(i-3) no tienen efecto en la resolución de f(i), así que solo Todo lo que necesita es una matriz de longitud 2, consulte el código para obtener más detalles.
inserte la descripción de la imagen aquí

Código:

import java.util.Map;

public class MinCostClimbingStairs {
    
    
    public static void main(String[] args) {
    
    
        MinCostClimbingStairs minCostClimbingStairs = new MinCostClimbingStairs();
        int[] cost = {
    
    1,100,1,1,100,1};
        int i = minCostClimbingStairs.minCostClimbingStairs3(cost);
        System.out.println(i);
    }
    public int minCostClimbingStairs(int[] cost){
    
    
        int len = cost.length;
        return Math.min(helper1(cost,len-2),helper1(cost,len-1));
    }

    private int helper1(int[] cost, int i) {
    
    
        if (i<2){
    
    
            return cost[i];
        }
        return Math.min(helper1(cost,i-1),helper1(cost,i-2))+cost[i];
    }
//利用数组来存储结果
    public int minCostClimbingStairs1(int[] cost) {
    
    
        int len = cost.length;//该数组的每个元素都初始化为0
        int[] dp = new int[len];
        helper(cost,len-1,dp);
        return Math.min(dp[len - 2],dp[len - 1]);
    }

    private void helper(int[] cost, int i, int[] dp) {
    
    
        if (i < 2){
    
    
            dp[i] = cost[i];
            //由于每级台阶往上爬的成本都是正数,因此如果某个问题f(i)之前已经求解过了,那么一定是一个大于0的数值。
        }else if (dp[i] == 0){
    
    
            helper(cost,i-2,dp);
            helper(cost,i-1,dp);
            dp[i] = Math.min(dp[i-2],dp[i-1])+cost[i];
        }
    }
//    自下而上,这个思路感觉要比自上而下的思路更好想
    public int minCostClimbingStairs2(int[] cost){
    
    
        int len = cost.length;
        int[] dp = new int[len];
        dp[0] = cost[0];
        dp[1] = cost[1];
        for (int i = 2; i < len; i++) {
    
    
            dp[i] = Math.min(dp[i-1],dp[i-2])+cost[i];
        }
        return Math.min(dp[len-2],dp[len-1]);
    }
    //优化空间复杂度解法
    public int minCostClimbingStairs3(int[] cost){
    
    
        int[] dp = new int[]{
    
    cost[0],cost[1]};
        for (int i = 2; i < cost.length; i++) {
    
    
//            用f(i)的结果覆盖f(i-2)的结果并不会带来任何问题
//            dp[0] 从开始到最终分别对应的是下标为0 2 4 6...的数组值,dp[1]同理。
//            求解的f(i)的结果保存在数组下标为“i%2”的位置。
            dp[i%2] = Math.min(dp[0],dp[1]) + cost[i];
        }
        return Math.min(dp[0],dp[1]);
    }
}

inserte la descripción de la imagen aquí

Supongo que te gusta

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