Day 35 贪心算法 Part03

  1. 携带研究材料(第六期模拟笔试)

这道题就是最标准的01背包问题,如果第一次见还是很难想出什么办法,用回溯(每个物品有选或不选两种状态,时间复杂度为$2^n$)暴力去做一定会超时。

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[] weight = new int[m];
        int[] value = new int[m];
        int[][] dp = new int[m][n+1];
        for(int i = 0; i < m; i++) weight[i] = sc.nextInt();
        for(int i = 0; i < m; i++) value[i] = sc.nextInt();
        
        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(j < weight[i]) dp[i][j] = dp[i-1][j];
                else dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i]);
            }
        }
        System.out.println(dp[m-1][n]);
    }
}
public class Main{ //滚动数组优化空间复杂度
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt(); // 物品种类数
        int n = sc.nextInt(); // 背包最大容量
        int[] weight = new int[m];
        int[] value = new int[m];
        int[] dp = new int[n+1];
        for(int i = 0; i < m; i++) weight[i] = sc.nextInt();
        for(int i = 0; i < m; i++) value[i] = sc.nextInt();
        for(int i = 0; i < m; i++)
            for(int j = n; j >= weight[i]; j--)
                dp[j] = Math.max(dp[j], dp[j-weight[i]]+value[i]);
        System.out.println(dp[n]);
    }
}

416. 分割等和子集

就是告诉我是01背包,他也还是不好做啊。没办法,去看了题解才做出来。还是按照动态规划的题目套路来。

  1. dp数组的含义:还是以2维数组来理解其含义(一维也是一致的,但二维更好讲清楚一些)。 dp[i,j] 代表了使用 0-i 间的任意物品组合,背包容量为j,所能装下的最大value。注意,对于本题,weight和value都是数字本身的值,背包总容量就是数组元素和的一半。
  2. 理解dp数组含义是这道题的重中之重。其实这道题就可以等价于,背包容量为数组元素和的一半,能否在给出的数字中,找到一部分其和恰好把背包填满。
class Solution {
    public boolean canPartition(int[] nums) {
        int sum = Arrays.stream(nums).sum();
        if(sum % 2 != 0) return false;
        sum /= 2;
        int n = nums.length;
        int[] dp = new int[sum+1];
        for(int i = 0; i < n; i++)
            for(int j = sum; j >= nums[i]; j--)
                dp[j] = Math.max(dp[j], dp[j-nums[i]] + nums[i]);
        return dp[sum] == sum;
    }
}
posted @ 2024-08-06 10:10  12点不睡觉还想干啥?  阅读(16)  评论(0)    收藏  举报