首页 > 其他分享 >leetcode 刷题day37动态规划Part06背包问题( 322. 零钱兑换、279.完全平方数、139.单词拆分、多重背包)

leetcode 刷题day37动态规划Part06背包问题( 322. 零钱兑换、279.完全平方数、139.单词拆分、多重背包)

时间:2024-10-08 15:19:43浏览次数:3  
标签:递推 背包 int day37 coins 322 true dp

322. 零钱兑换

思路:每种硬币的数量是无限的,是典型的完全背包问题。但是题目要求等于目标值的最小硬币个数。所以这里需要对动规五部曲进行分析。

动规五部曲:

1、确定dp数组以及下标的含义
dp[j]:凑足总额为j所需钱币的最少个数为dp[j]

2、确定递推公式
凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j];
dp[j] 要取所有 dp[j - coins[i]] + 1 中最小的。

递推公式:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);

3、dp数组如何初始化
首先凑足总金额为0所需钱币的个数一定是0,那么dp[0] = 0;考虑到递推公式取最小值,dp[j]下标非0的元素都是应该是最大值。

4、确定遍历顺序
本题求钱币最小个数,钱币有顺序和没有顺序都可以,都不影响钱币的最小个数。所以本题并不强调集合是组合还是排列。两种内外层循环都是可以的。这里采用coins放在外循环,target在内循环的方式。

本题钱币数量可以无限使用,那么是完全背包。所以遍历的内循环是正序

5、举例推导dp数组

代码如下:

class Solution {
    public int coinChange(int[] coins, int amount) {
        int max=Integer.MAX_VALUE;
        int[] dp=new int[amount+1];
        dp[0]=0;
        for(int j=1;j<=amount;j++){
            dp[j]=max;
        }
        for(int i=0;i<coins.length;i++){
            for(int j=coins[i];j<=amount;j++){
                 //只有dp[j-coins[i]]不是初始最大值时,该位才有选择的必要
                if (dp[j - coins[i]] != max) {
                    dp[j]=Math.min(dp[j],dp[j-coins[i]]+1);
                }
            }
        }
        if(dp[amount]==max) return -1;
        else return dp[amount];
    }
}

279.完全平方数

思路:这个题和上一题相同,都是求最小个数。
dp[j]就是满足和为j的平方数最小个数;
递推公式:dp[j]=min(dp[j];dp[j-i*i]+1);
初始化:dp[0]=0,因为平方数是从1开始的;
遍历顺序:内外循环都可以,选物体在外面,背包容量在里面;数字可以重复选取,完全背包,内循环正序。

代码如下:

class Solution {
    public int numSquares(int n) {
        int[] dp=new int[n+1];
        int max=Integer.MAX_VALUE;
        for(int j=0;j<=n;j++){
            dp[j]=max;
        }
        dp[0]=0;
        for(int i=1;i*i<=n;i++){
            for(int j=i*i;j<=n;j++){
                dp[j]=Math.min(dp[j],dp[j-i*i]+1);
            }
        }
        return dp[n];
    }
}

139.单词拆分

思路:字典可以重复使用,所以是完全背包问题。

1、确定dp数组以及下标的含义
dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。

2、确定递推公式
如果dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true(j < i )。

所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。

3、dp数组如何初始化
dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。

下标非0的dp[i]初始化为false,只要没有被覆盖说明都是不可拆分为一个或多个在字典中出现的单词。

4、确定遍历顺序
题目中说是拆分为一个或多个在字典中出现的单词,所以这是完全背包。

本题是求排列数,所以先遍历背包,再遍历物品。

代码如下:

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        boolean[] dp=new boolean[s.length()+1];
        dp[0]=true;
        for(int j=1;j<=s.length();j++){
            dp[j]=false;
        }
        for(int j=1;j<=s.length();j++){
            for(String word:wordDict){
                int len=word.length();
                if(j>=len && dp[j-len] && word.equals(s.substring(j-len,j))){
                    dp[j]=true;
                }
            }
        }
        return dp[s.length()];
    }
}

多重背包

本质上和01背包相同,限制了每个物品可以用的数量,只需要多加一层循环限制物品数量即可。

for (int i = 0; i < n; i++) {
            for (int j = bagWeight; j >= weight[i]; j--) {
                //遍历每种物品的个数
                for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) {
                    dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);
                }
            }
        }

标签:递推,背包,int,day37,coins,322,true,dp
From: https://blog.csdn.net/m0_51007517/article/details/142757843

相关文章

  • P8392 [BalticOI 2022 Day1] Uplifting Excursion(特殊背包问题)
    题意简述有\(2m+1\)种物品,体积分别为\(-m\simm\),每种物品有\(a_i\)个。你需要选出尽可能多数量的物品,使得物品体积和为\(l\)。\(m\le300,a_i,|l|\le10^{18}\)分析此题属于“背包容量极大,物品体积极小”的特殊背包问题。考虑背包问题的经典错误贪心:按照性价比降序排......
  • 2024-2025-1 20241322《计算机基础与程序设计》第二周学习总结
    作业信息这个作业属于哪个课程https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP这个作业要求在哪里https://www.cnblogs.com/rocedu/p/9577842.html#WEEK02这个作业的目标<数字化信息安全自学教材计算机科学概论(第七版)第1章并完成云班课测试《C语言程序......
  • 2024.10.4 ROS第五章结束,复习背包问题模型 + codeforces刷刷题
    项目学习总结ROS第五章主要是学习了坐标变换,实际用途还是好理解的,比方说地面基地控制无人机追鸟。坐标变换主要是用tf这个包实现的。可以实现静态坐标变换,动态坐标变换和多坐标变换。静态和动态变换的关键函数:ps_out=buffer.transform(ps,"base_link");动态变换里面主要是......
  • 南沙C++信奥赛陈老师解一本通题 1270:【例9.14】混合背包
    ​ 【题目描述】一个旅行者有一个最多能装V公斤的背包,现在有n件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn。有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包)。求解将哪些物品装入背包可使这些物品的费用总......
  • <min/max,+>卷积与背包优化
    【前置知识】convex与concave:这是对于数组的概念。类比函数,下凸就是convex,上凸就是concave。【<min,+>卷积问题】考虑两个数组\(a_{1\simn},b_{1\simm}\),定义它们的<min,+>卷积结果\(c\):\(|c|=n+m\)。\(c_i=\min_{j+k=i}\{a_j+b_k\}\)。因为普通的卷积是\(\s......
  • 多重背包
    intw[maxn],v[maxn];//w[i]代表第i种物品价值v[i]代表体积intf[maxn][maxm];//前i种物品用了j的体积所能得到的最大价值intcnt=0;//总共拆成了多少个物品for(inti=1;i<=n;++i){intw,u,v;//价值,个数,体积cin>>w>>v>>u;intk=1;//先拆......
  • leetcode刷题day34|动态规划Part03 背包问题(01背包问题 二维、01背包问题 一维、416.
    0-1背包问题二维动规五部曲1、确定dp数组以及下标的含义dp[i][j]表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。(取物品时可以是取0-i的任意一个,或者是他们的组合)2、确定递推公式不放物品i:背包容量为j,里面不放物品i的最大价值是dp[i-1][j]......
  • 1267:【例9.11】01背包问题(从二维优化一维dp问题)
    代码如下:#include<iostream>usingnamespacestd;intdp[10010],w[200],c[200];intmain(){ intm,n; cin>>m>>n; for(inti=1;i<=n;i++) { cin>>w[i]>>c[i]; } for(inti=1;i<=n;i++) { for(intj=m;j......
  • 【DP解密多重背包问题】:优化策略与实现
    文章目录什么是多重背包问题?多重背包问题的数学模型例题多重背包问题Ⅰ多重背包问题Ⅱ总结什么是多重背包问题?多重背包问题是一个经典的组合优化问题。与标准背包问题不同,在多重背包问题中,每种物品可以选择多个,而不是只选择一次。具体来说,给定一个背包的容量和若......
  • 动态规划(有背包问题)
    目录1.动态规划的介绍2.动态规划的例题第1道题数字三角形(如果想看递归写法可以到我的记忆化递归里去看看记忆化递归_将递归程序记忆化-CSDN博客)第2道题最长公共子序列(模板) 第3道题 最长上升子序列第4道题最大子段和背包系列问题01背包完全背包1.动态规划......