Day39 代码随想录(1刷) 动态规划 0-1背包

这篇具有很好参考价值的文章主要介绍了Day39 代码随想录(1刷) 动态规划 0-1背包。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

题目描述

小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间,并且具有不同的价值。 

小明的行李空间为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料只能选择一次,并且只有选与不选两种选择,不能进行切割。

输入描述

第一行包含两个正整数,第一个整数 M 代表研究材料的种类,第二个正整数 N,代表小明的行李空间。

第二行包含 M 个正整数,代表每种研究材料的所占空间。 

第三行包含 M 个正整数,代表每种研究材料的价值。

输出描述

输出一个整数,代表小明能够携带的研究材料的最大价值。

输入示例
6 1
2 2 3 1 5 2
2 3 1 5 4 3
输出示例
5
提示信息

小明能够携带 6 种研究材料,但是行李空间只有 1,而占用空间为 1 的研究材料价值为 5,所以最终答案输出 5。 

数据范围:
1 <= N <= 5000
1 <= M <= 5000
研究材料占用空间和价值都小于等于 1000

状态:完成

思路:这是一个存粹的0-1背包的入门问题,先用二维的dp数组解决,dp[i][j]表示背包最大容量为j的时候从物品【0-i】任取,所以最后一个格就是背包容量是N时的最大价值,状态转移方程也是很好理解的dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-weights[i]]+values[i]),意思就是对比不取物品i时在这个容量时的最大价值和取这个物品在背包容量允许的情况下的价值。该题也是要初始化,dp[0][i]表示取物品0的最大价值。二维数组时先遍历物品还是背包容量都是可以的。

可以从上面的二维数组思路中看出状态转移的时候其实就是把dp[i-1]行的与dp[i-1][j-weights[i]]+values[i]进行对比所以我们可以直接用一个一维数组解决问题,这个数组中dp[i]表示背包容量为i的最大价值,转移方程与二维数组的基本一致就是dp[i]跟dp[i-weights[i]]+values[i]进行对比,但这里只能从大到小进行容量的遍历,因为如果小到大则会重复加了。

dp二维数组:

import java.util.*;
public class Main{
    public static void main (String[] args) {
        Scanner sc=new Scanner(System.in);
        String l1=sc.nextLine();
        int M=Integer.valueOf(l1.split(" ")[0]),N=Integer.valueOf(l1.split(" ")[1]);
        int[] weights=new int[M];
        int[] values=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 i=0;i<=N;i++){
            if(weights[0]<=i)
            dp[0][i]=values[0];
        }
        for(int i=1;i<M;i++){
            for(int j=1;j<=N;j++){
                if(j-weights[i]<0) 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]);
        
    }
}

 dp一维数组:

import java.util.*;
public class Main{
    public static void main (String[] args) {
        Scanner sc=new Scanner(System.in);
        String l1=sc.nextLine();
        int M=Integer.valueOf(l1.split(" ")[0]),N=Integer.valueOf(l1.split(" ")[1]);
        int[] weights=new int[M];
        int[] values=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>0;j--){
                if(j-weights[i]<0) break;
                dp[j]=Math.max(dp[j],dp[j-weights[i]]+values[i]);
            }
        }
        System.out.println(dp[N]);
        
    }
}

416. 分割等和子集

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

示例 1:

输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

示例 2:

输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。

提示:

  • 1 <= nums.length <= 200
  • 1 <= nums[i] <= 100

状态:没想出来

思路:这个是恰好相等类的问题,这里的物品质量跟物品价格都一致,我们使用一维dp数组去解决这个问题,dp[i]表示和为i时的最大数值,这题明显只有和为数组和的半时才能得到两个相等和的子数组。所以最后只要dp[target]==target表示存在这样的子数组。

class Solution {
    public boolean canPartition(int[] nums) {
        int sum=0;
        for(int a:nums){
            sum+=a;
        }
        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>=0;j--){
                if(j-nums[i]<0) break;
                dp[j]=Math.max(dp[j],dp[j-nums[i]]+nums[i]);
            }
        }
        return dp[target]==target;
    }
}

 文章来源地址https://www.toymoban.com/news/detail-856146.html

到了这里,关于Day39 代码随想录(1刷) 动态规划 0-1背包的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 动态规划01背包问题-代码随想录-刷题笔记

    有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。 每件物品只能用一次 ,求解将哪些物品装入背包里物品价值总和最大。 二维dp数组01背包 确定dp数组以及下标的含义 是使用二维数组,即 dp[i][j] 表示从下标为[0-i]的物品里任意取,

    2024年02月07日
    浏览(34)
  • 二刷代码随想录——动态规划day40

    一个本硕双非的小菜鸡,备战24年秋招,计划二刷完卡子哥的刷题计划,加油! 二刷决定精刷了,于是参加了卡子哥的刷题班,训练营为期60天,我一定能坚持下去,迎来两个月后的脱变的,加油! 推荐一手卡子哥的刷题网站,感谢卡子哥。代码随想录 终于来到了守关boss。

    2024年03月11日
    浏览(33)
  • 代码随想录Day41:动态规划Part3

    讲解前: 毫无头绪 讲解后: 这道题的动态思路一开始很不容易想出来,虽然dp数组的定义如果知道是动态规划的话估摸着可以想出来那就是很straight forward dp定义:一维数组dp[i], i 代表整数的值,dp[i] 代表将整数 i 拆分的话可以获得的最大乘积 然后呢就是定义递归推导式了,

    2024年04月27日
    浏览(31)
  • 代码随想录第44天|动态规划:完全背包理论基础 518.零钱兑换II 377. 组合总和 Ⅳ

    代码随想录 (programmercarl.com) 动态规划之完全背包,装满背包有多少种方法?组合与排列有讲究!| LeetCode:518.零钱兑换II_哔哩哔哩_bilibili 完全背包和01背包问题唯一不同的地方就是,每种物品有无限件 。 完全背包中的物品可以添加多次,所以要从小到大遍历: 518. 零钱兑换

    2024年04月25日
    浏览(32)
  • 【代码随想录】Day 49 动态规划10 (买卖股票Ⅰ、Ⅱ)

    https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/ dp[i]表示在第i天时,卖/不卖股票能获得的最大利润: 1、卖股票:dp[i] = prices[i] -minPrice(i天以前的最低价格) 2、不卖股票:dp[i] = dp[i-1](因为不卖股票,所以状态和前一天保持一致) ∴dp[i] = max(dp[i-1], prices[i] - minPrice); https

    2024年02月09日
    浏览(32)
  • 代码随想录 day38 第九章 动态规划part01

    ●  理论基础 ●  509. 斐波那契数 ●  70. 爬楼梯 ●  746. 使用最小花费爬楼梯 理论基础 解决动态规划必须要想清楚的点 dp数组以及下标的含义 递推公式 dp数组如何初始化 遍历顺序 打印数组 检查结果 关联 leetcode 509. 斐波那契数 思路 动规五部曲 dp数组以及下标的含义

    2024年04月17日
    浏览(31)
  • 【Day52】代码随想录之动态规划_打家劫舍

    动态规划理论基础 动规五部曲: 确定dp数组 下标及dp[i] 的含义。 递推公式:比如斐波那契数列 dp[i] = dp[i-1] + dp[i-2]。 初始化dp数组。 确定遍历顺序:从前到后or其他。 打印。 出现结果不正确: 打印dp日志和自己想的一样:递推公式、初始化或者遍历顺序出错。 打印dp日志和

    2024年02月22日
    浏览(38)
  • 【随想录学习】——第十章 动态规划(0-1背包+完全背包)

    动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。 所以动态规划中每一个状态一定是由上一个状态推导出来的, 这一点就区分于贪心 ,贪心没有状态推导,而是从局部直接选最优的, dp数组表示斐波那契数列,dp[i]表示

    2024年01月19日
    浏览(49)
  • 代码随想录day42(背包)

    2024年02月13日
    浏览(27)
  • 代码随想录 day44 完全背包

    class Solution { public:     int change(int amount, vectorint coins) {         vector int dp(amount+1,0);         dp[0]=1;         for(int i=0;icoins.size();i++){             for(int j=coins[i];j=amount;j++){                 dp[j]+=dp[j-coins[i]];             }         }  

    2024年02月15日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包