代码随想录算法训练营第35天 | 01背包问题 二维 一维 416. 分割等和子集

01背包问题 二维

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

代码随想录

视频讲解:带你学透0-1背包问题!| 关于背包问题,你不清楚的地方,这里都讲了!| 动态规划经典问题 | 数据结构与算法_哔哩哔哩_bilibili

dp[i][j]数组含义:从0-i物品中任取,放入容量为j的背包中时,最大的价值

递推公式:dp[i][j] = Math.max(dp[i - 1][j] , dp[i - 1][j - space[i]] + value[i]);  放i和不放i哪个价值最大

if(space[i] > j)  dp[i][j] = dp[i - 1][j];     //如果i的体积比j大,不能放i

import java.util.*;
class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();
        int[] space = new int[m];
        int[] value = new int[m];
        for(int i = 0;i < m;i++){
            space[i] = sc.nextInt();
        }
        for(int i = 0;i < m;i++){
            value[i] = sc.nextInt();
        }

        int[][] dp = new int[m][n + 1];
        //初始化行
        for(int i = 1;i < n + 1;i++){
            if(space[0] <= i)dp[0][i] = value[0];
        }
        //初始化列
        for(int i = 0;i < m;i++){
            dp[i][0] = 0;
        }
        for(int i = 1;i < m;i++){
            for(int j = 1;j < n + 1;j++){
                if(space[i] > j){//如果i的体积比j大,不能放i
                    dp[i][j] = dp[i - 1][j];
                }else{
                    dp[i][j] = Math.max(dp[i - 1][j],
                    dp[i - 1][j - space[i]] + value[i]);
                }
            }
        }
        System.out.println(dp[m - 1][n]);
    }
}

01背包问题 一维

代码随想录

视频讲解:带你学透01背包问题(滚动数组篇) | 从此对背包问题不再迷茫!_哔哩哔哩_bilibili

import java.util.*;
class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        // 读取 M 和 N
        int M = scanner.nextInt();  // 研究材料的数量
        int N = scanner.nextInt();  // 行李空间的大小

        int[] costs = new int[M];   // 每种材料的空间占用
        int[] values = new int[M];  // 每种材料的价值

        // 输入每种材料的空间占用
        for (int i = 0; i < M; i++) {
            costs[i] = scanner.nextInt();
        }

        // 输入每种材料的价值
        for (int j = 0; j < M; j++) {
            values[j] = scanner.nextInt();
        }

        // 创建一个动态规划数组 dp,初始值为 0
        int[] dp = new int[N + 1];

         // 外层循环遍历每个类型的研究材料
        for(int i = 0;i < M;i++){
            // 内层循环从 N 空间逐渐减少到当前研究材料所占空间
            for(int j = N;j >= costs[i];j--){
                // 考虑当前研究材料选择和不选择的情况,选择最大值
                dp[j] = Math.max(dp[j],dp[j - costs[i]] + values[i]);
                
            }
        }
        System.out.println(dp[N]);
        scanner.close();
    }
}

416. 分割等和子集

本题是 01背包的应用类题目

代码随想录

视频讲解:动态规划之背包问题,这个包能装满吗?| LeetCode:416.分割等和子集_哔哩哔哩_bilibili

nums[i]既是空间又是价值

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[] dp = new int[sum / 2 + 1];
        Arrays.fill(dp,0);
        for(int i = 0;i < nums.length;i++){
            for(int j = sum/2;j >= nums[i];j--){
                dp[j] = Math.max(dp[j],dp[j - nums[i]] + nums[i]);
                if(dp[sum/2] == sum/2)return true;//剪枝,发现可以装到sum/2就可以了
            }
        }
        if(dp[sum / 2] == sum / 2)return true;
        else return false;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值