Serie de planificación dinámica "Change Exchange II"

Dadas monedas de diferentes denominaciones coinsy un monto total amount. Escribe una función para calcular las monedas que pueden formar la cantidad total 组合数. Suponga que hay infinitas monedas de cada denominación.

Esta pregunta es 0-1una variante del problema de la mochila, que es un problema de mochila completo, entonces, ¿qué es un problema de mochila completo?

Repasemos de nuevo el problema de la mochila 0-1 : le damos una Wmochila y Nartículos (cada artículo es diferente) que se pueden cargar con un peso de 1 , y cada artículo tiene dos atributos: peso y valor. iEl peso de la primer artículo es wt[i]y el valor está val[i]. Ahora le permiten usar esta mochila para empacar el artículo, ¿cuál es el valor máximo que se puede cargar?

0-1El número de artículos en el problema de la mochila es limitado. Para ser precisos, cada artículo es único y hay monedas ilimitadas de cada denominación aquí. Es decir 完全背包问题, la idea es la misma que la de la mochila 0-1, pero el estado la ecuación de transición cambia ligeramente.

Podemos 0-1solucionar este problema según la idea de mochila :

Comparamos monedas de diferentes denominaciones con 0-1artículos en el problema de la mochila, y comparamos la cantidad total con la capacidad de la mochila, de modo que se pueda transformar en un modelo de problema de mochila para su solución.

  1. El primer paso: borrar "estado" y "elección"

Hay dos estados, a saber, "la capacidad de la mochila" y "elementos opcionales", la opción es "empacar en la mochila" o "no en la mochila".

for 状态1 in 状态1的所有取值:
    for 状态2 in 状态2的所有取值:
        for ...
            dp[状态1][状态2][...] = 计算(选择1,选择2...)
  1. Definición clara de matrizdp

dp[i][j]Se define de la siguiente manera: solo los idos primeros artículos, cuando la capacidad de la mochila jcuando hay dp[i][j]formas de llenar la mochila.

La conversión a un modelo de cambiador de monedas es: use solo coinsel ivalor nominal de las monedas del frente, si desea la cantidad de Couchu j, hay dp[i][j]tipos de métodos de error.

El caso base es dp[0][..] = 0, dp[..][0] = 1. Porque si no usa el valor nominal de ninguna moneda, no puede recuperar ninguna cantidad, si la cantidad objetivo es 0, entonces "gobernar sin hacer nada" es la única forma de compensar.

Nuestro objetivo final es encontrar dp[N][amount], cuál Nes el coinstamaño de la matriz.

  1. Según "elección", piense en la lógica de la transición de estado

Si no utiliza coins[i]el valor nominal de la moneda, entonces la denominación de Couchu debe ser de jvarios métodos dp[i][j]iguales dp[i-1][j], heredado los resultados anteriores.

Si usa coins[i]el valor nominal de la moneda, dp[i][j]debería ser igual dp[i][j-coins[i-1]].

Primero, como ies desde el principio, coinsel índice es el i-1tiempo que representa el ivalor nominal de las monedas.

dp[i][j-coins[i-1]]No es difícil entender que si decides usar esta moneda, debes prestar atención a cómo cobrar la cantidad j - coins[i-1].

En resumen, son dos opciones, y queremos preguntar por dp[i][j]un "número total de especies y error", por lo que dp[i][j]el valor debe ser mayor que la suma de los resultados de las dos opciones:

class Solution {
    
    
    int change(int amount, int[] coins) {
    
    
        int n = coins.length;
        int[][] dp = amount int[n + 1][amount + 1];
        for (int i = 0; i <= n; i++) {
    
    
            dp[i][0] = 1;
        }
        for (int i = 1; i <= n; i++) {
    
    
            for (int j = 1; j <= amount; j++){
    
    
              	if (j - coins[i-1] >= 0){
    
    
                    dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i-1]];
                }else {
    
    
                    dp[i][j] = dp[i - 1][j];
                }
            }   
        }
        return dp[n][amount];
    }
}

Además, podemos descubrir a través de la observación, dptransferir la matriz y solo dp[i][..]y dp[i-1][..]relevantes:

Inserte la descripción de la imagen aquí
Por lo tanto, el estado se puede comprimir para reducir aún más la complejidad espacial del algoritmo:

class Solution {
    
    
    public int change(int amount, int[] coins) {
    
    
        int n = coins.length;
        int[] dp = new int[amount + 1];
        dp[0] = 1; 
      
        for (int i = 0; i < n; i++){
    
    
            for (int j = 1; j <= amount; j++){
    
    
                if (j - coins[i] >= 0){
    
    
                    dp[j] += dp[j-coins[i]];
                }
            }
        }
        return dp[amount];
    }
}

Incluso puede hacer esto:

class Solution {
    
    
    public int change(int amount, int[] coins) {
    
    
        int[] dp = new int[amount + 1];
        dp[0] = 1;

        for (int coin : coins) {
    
    
            // j直接从coin开始,避免了j - coins[i] >= 0的判断
            for (int j = coin; j <= amount; j++) {
    
       
              	dp[j] += dp[j - coin];
            }
        }
        return dp[amount];
    }
}

Complejidad de tiempo O (cantidad N *)

Complejidad espacial O (cantidad)

Supongo que te gusta

Origin blog.csdn.net/weixin_44471490/article/details/109132075
Recomendado
Clasificación