Problema de mochila del día 42 de registro de preguntas de algoritmo | 416. Dividir subconjuntos de suma igual

Dependiendo de la cantidad de artículos y cómo se accede a ellos, el problema de la mochila se puede dividir en 01 mochilas (un solo artículo), mochilas completas (hay innumerables artículos), mochilas múltiples (diferente número de artículos) y mochilas agrupadas (empaquetadas en grupos, cada grupo elige como máximo uno). Solo concéntrate en dominar la mochila 01 y la mochila completa. Hay muchos problemas que no se examinarán directamente en forma de mochila, por lo que enfrentar el problema puede requerir un proceso de pensamiento para convertirlo primero en un problema de mochila. Primero analicemos estas dos mochilas usando un método de cinco pasos.

01 mochila 

1. dp [i] [j], que representa el valor máximo que se puede obtener seleccionando elementos aleatoriamente de 0 a i-1 cuando la capacidad de la mochila es j;

2. Solo hay dos formas de elementos, tomar o no tomar, por lo que dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] +valor [i]);

3. Cuando i = 0, j = 0, los artículos disponibles son 0, la capacidad de la mochila es 0, dp[i][0] = 0, i = 1, cuando j >= peso[i], dp[1] [j] = valor[1];

4. El orden transversal puede ser i primero, luego j o j luego i, porque dp [i] [j] solo está relacionado con el elemento superior izquierdo, pero desde la perspectiva de la comprensión y el almacenamiento subyacente, es mejor primero yo entonces j;

5. Di algunos ejemplos y descubrí que no había ningún problema.

Complejidad del tiempo O(n^2), complejidad del espacio En), el código es el siguiente:

void test_2_wei_bag_problem1() {
    vector<int> weight = {1, 3, 4};
    vector<int> value = {15, 20, 30};
    int bagweight = 4;

    // 二维数组
    vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));

    // 初始化
    for (int j = weight[0]; j <= bagweight; j++) {
        dp[0][j] = value[0];
    }

    // weight数组的大小 就是物品个数
    for(int i = 1; i < weight.size(); i++) { // 遍历物品
        for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
            if (j < weight[i]) dp[i][j] = dp[i - 1][j];
            else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

        }
    }

    cout << dp[weight.size() - 1][bagweight] << endl;
}

int main() {
    test_2_wei_bag_problem1();
}

Optimizar el espacio

Comprimido a una matriz unidimensional:

dp[j] = max(dp[j], dp[j-peso[i]]+valor[i]);

Tenga en cuenta que el orden de recorrido sigue siendo doble, pero la capacidad de la mochila j debe recorrerse de atrás hacia adelante.

Preguntas de practica

416. Dividir subconjuntos de suma igual - LeetCode

Estado: verifique la idea y AC después de la depuración.

Hay dos dificultades en esta pregunta. La primera es darse cuenta de que la suma de puntos/2 se puede utilizar para emitir juicios. Si sigues la idea descrita en la pregunta, llegarás muy lejos; la segunda es cómo adaptarte a este problema utilizando el marco del problema de la mochila.

Con la condición de que la capacidad de la mochila sea suma/2, ¿podemos encontrar una combinación tal que dp[suma/2] = suma/2?

El código se muestra a continuación:

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum = 0;
        int len = nums.size();
        for(int n : nums){
            sum += n;
        }
        if(sum % 2 == 1) return false;
        int target = sum / 2;
        vector<int> dp(10001, 0);
        for(int i = 0; i < len; ++i){
            for(int j = target; j >= nums[i]; --j){
                dp[j] = max(dp[j], dp[j-nums[i]]+nums[i]);
            }
        }
        if(dp[target] == target) return true;
        return false;
    }
};

Supongo que te gusta

Origin blog.csdn.net/qq_40395888/article/details/132420258
Recomendado
Clasificación