Day 42 | 动态规划 01背包问题,二维 、 01背包问题,一维 、 416. 分割等和子集

01背包问题,二维

题目
文章讲解
视频讲解

思路:首先,初始化一个二维数组dp,其中dp[i][j]表示在前i个物品中,背包容量为j时能够获得的最大价值。然后,根据0-1背包的特性,使用动态规划的思想来填充dp数组。

在填充dp数组的过程中,首先处理第一个物品的情况,对于所有背包容量大于等于第一个物品重量的情况,将dp[0][j]设置为第一个物品的价值。然后,对于剩下的物品,根据当前物品是否放入背包来更新dp数组。具体来说,如果当前物品的重量大于当前背包容量,无法放入该物品,因此dp[i][j]等于dp[i-1][j];如果当前物品的重量小于等于当前背包容量,可以选择放入或不放入该物品,取两者中的最大值作为dp[i][j]的值。

最终,dp[M-1][N]就是在前M个物品中,背包容量为N时能够获得的最大价值,即为问题的解。

注意:创建数组时数组自动初始化。由左上角的值推导出dp[i][j],所以最左一列和最上一行需要初始化

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int M = sc.nextInt();
        int N = sc.nextInt();  

        int[] values = new int[M];
        int[] weights = new int[M];

        for (int i = 0; i < M; i++) {
            weights[i] = sc.nextInt();
        }

        for (int i = 0; i < M; i++) {
            values[i] = sc.nextInt();
        }

        int[][] dp = new int[M][N + 1];

        for (int j = weight[0]; j <= N; j++) {
            dp[0][j] = value[0];
        }

        for (int i = 1; i < M; i++) {
            for (int j = 0; j <= N; j++) {
                if (weights[i] > j) {
                    dp[i][j] = dp[i - 1][j];
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weights[i]] + values[i]);
                }
            }
        }
        System.out.println(dp[M - 1][N]);
    }
}


01背包问题,一维

题目
文章讲解
视频讲解

思路:一维相当于继承上一层的 i ,初始化时是将所有初值设置为 0 ,遍历时先遍历物品,之后由后向前编历(由前向后遍历会出现重复录入的问题)
dp[j] 表示容量为 j 的背包可装入最大值为 dp[j] ; 更新公式:dp[j] = max(dp[j],dp[j-weights[i]]+values[i]) ; 初始化设置为 0 是为了保证更新时不会被初始值覆盖

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int M = sc.nextInt();
        int N = sc.nextInt();

        int[] values = new int[M];
        int[] weights = new int[M];

        for (int i = 0; i < M; i++) {
            weights[i] = sc.nextInt();
        }

        for (int i = 0; i < M; i++) {
            values[i] = sc.nextInt();
        }

        int[] dp = new int[N + 1];

        for (int i = 0; i < M; i++) {
            for (int j = N; j >= weights[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - weights[i]] + values[i]);
            }
        }
        System.out.println(dp[N]);
    }
}

416. 分割等和子集

题目
文章讲解
视频讲解

思路:

class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        if (sum % 2 == 1)
            return false;
        int target = sum / 2;
        int[][] dp = new int[nums.length][target+1];
        for (int i = 1; i < nums.length; i++) {
            for (int j = 0; j <= target; j++) {
                if(nums[i]<=j)
                    dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j - nums[i]] + nums[i]);
                else 
                    dp[i][j]=dp[i-1][j];
            }
        }
        return dp[nums.length-1][target] == target;
    }
}
class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        if (sum % 2 == 1)
            return false;
        int target = sum / 2;
        int[] dp = new int[target+1];
        for (int i = 0; i < nums.length; i++) {
            for (int j = target; j >= nums[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
            }
        }
        return dp[target] == target;     
    }
}

有点就是整不明白,看了两天了,有点捣鼓不明白,等我整明白再回来补

你可能感兴趣的:(二月红,动态规划,算法)