Day39 | 动态规划 :完全背包应用 零钱兑换零钱兑换II

Day39 | 动态规划 :完全背包应用 零钱兑换&&零钱兑换II

动态规划应该如何学习?-CSDN博客

01背包模板 | 学习总结-CSDN博客

完全背包模板总结-CSDN博客

难点:

代码都不难写,如何想到完全背包并把具体问题抽象为完全背包才是关键

文章目录

  • Day39 | 动态规划 :完全背包应用 零钱兑换&&零钱兑换II
    • 322.零钱兑换
      • 思路分析:
      • 1.回溯法
      • 2.记忆化搜索
      • 3.动态规划
      • 4.滚动数组
    • 518.零钱对换II
      • 思路分析:
      • 1.回溯暴力枚举
      • 2.记忆化搜索
      • 3. 1:1翻译为动态规划
      • 4.滚动数组优化
    • 遍历顺序先遍历背包容量后遍历物品和先遍历物品后背包容量
      • 先遍历物品后遍历背包容量,求的是可以凑成target的组合
      • 先背包容量后物品,求的是可以凑成target的排列

322.零钱兑换

[322. 零钱兑换 - 力扣(LeetCode)](https://leetcode.cn/problems/partition-equal-subset-sum/description/)

思路分析:

完全背包模板总结-CSDN博客

322. 零钱兑换 - 力扣(LeetCode)

套用模板时候的注意点

1.这道题的金币可以重复选,所以是完全背包不是01背包

2.这道题是返回最少的金币数量,所以dfs/dp的含义就是前i种金币可以凑成金额为c的面额的最少金币数量是多少

3.由于求的是金币数量,所以面额amount就是背包的容量,物品的重量就是自己的面额,每个物品的价值都为1,因为dfs和dp的含义是最少的金币的数量是多少

4.求的是最少,所以要把max换成min,初始化的时候要初始化为INT_MAX/2而不是0(除以2是因为返回的INT_MAX+1后会溢出,导致报错)

1.回溯法

1.参数和返回值

i是物品编号,表示从前i个物品里面选

c是容量

coins是w[i]

v[i]的值全都为1这里就不写了

int dfs(int i,int c,vector<int>& coins)

2.终止条件

i小于0说明到了树形结构的最下面了

如果同时容量c==0,那说明正好可以凑够,我们就找到了一个合法的方案,返回0(不返回1的原因是我们dfs的含义是最少金币的数量,而不是能凑够amount的方案数量)

如果容量不是0就凑不够,返回INT_MAX/2

如果容量不够当前的硬币,那就递归下一个物品去了,最后返回的就是在前i-1种金币能凑够amount的最小金额数

		if(i<0)if(c==0)return 0;elsereturn INT_MAX/2;if(c<coins[i])return dfs(i-1,c,coins);

3.本层逻辑

递归公式max换成min

 return min(dfs(i-1,c,coins),dfs(i,c-coins[i],coins)+1);

完整代码:

当然是超时的

class Solution {
public:int dfs(int i,int c,vector<int>& coins){if(i<0)if(c==0)return 0;elsereturn INT_MAX/2;if(c<coins[i])return dfs(i-1,c,coins);return min(dfs(i-1,c,coins),dfs(i,c-coins[i],coins)+1);}int coinChange(vector<int>& coins, int amount) {int res=dfs(coins.size()-1,amount,coins);if(res<INT_MAX/2)return res;elsereturn -1;}
};

2.记忆化搜索

就是还是全都初始化为-1,每次返回前给dp赋值,碰到不是-1的那就是算过的,那就直接返回计算过的结果,不需要再次递归了

完整代码:

class Solution {
public:int dfs(int i,int c,vector<int>& coins,vector<vector<int>>& dp){if(i<0)if(c==0)return 0;elsereturn INT_MAX/2;if(dp[i][c]!=-1)return dp[i][c];if(c<coins[i])return dp[i][c]=dfs(i-1,c,coins,dp);return dp[i][c]=min(dfs(i-1,c,coins,dp),dfs(i,c-coins[i],coins,dp)+1);}int coinChange(vector<int>& coins, int amount) {vector<vector<int>> dp(coins.size(),vector<int>(amount+1,-1));int res=dfs(coins.size()-1,amount,coins,dp);if(res<INT_MAX/2)return res;elsereturn -1;}
};

3.动态规划

笔者选择的是dp数组的物品编号从1开始

递归的边界条件是

i<0的时候c==0是返回0的。而我们这里的dp数组编号从1开始,那就是i<1且c==0的时候是等于0的

所以dp[0][0]的初始值就为0,其他的都是INT_MAX/2

class Solution {
public:int coinChange(vector<int>& coins, int amount) {vector<vector<int>> dp(coins.size()+1,vector<int>(amount+1,INT_MAX/2));dp[0][0]=0;for(int i=1;i<=coins.size();i++)for(int j=0;j<=amount;j++)if(j<coins[i-1])dp[i][j]=dp[i-1][j];elsedp[i][j]=min(dp[i-1][j],dp[i][j-coins[i-1]]+1);if(dp[coins.size()][amount]<INT_MAX/2)return dp[coins.size()][amount];elsereturn -1;}
};

4.滚动数组

把第一维度全都删掉即可

class Solution {
public:int coinChange(vector<int>& coins, int amount) {vector<int> dp(amount+1,INT_MAX/2);dp[0]=0;for(int i=1;i<=coins.size();i++)for(int j=coins[i-1];j<=amount;j++)dp[j]=min(dp[j],dp[j-coins[i-1]]+1);if(dp[amount]<INT_MAX/2)return dp[amount];elsereturn -1;}
};

518.零钱对换II

[518. 零钱兑换 II - 力扣(LeetCode)](https://leetcode.cn/problems/ones-and-zeroes/description/)

思路分析:

这回求的是方案数量很明显,求方案数量那dfs的的含义就是在前i种金币里面有多少种方法可以恰好凑够当前的容量c,递推公式和01背包变形类似

就把max换成+就可以了,即两种情况的方案数加起来就是当前i,c的总方案数量

1.回溯暴力枚举

就挑重点说吧

终止条件如果c==0说明恰好可以凑够,那说明我们找到了合法的方案,由于我们dfs的含义是返回合法的方案数量,所以我们每找到一个合法方案返回的就是1,否则就是0.

完整代码

当然是超时的

class Solution {
public:int dfs(int i,int c,vector<int>& coins){if(i<0)if(c==0)return 1;elsereturn 0;if(c<coins[i])return dfs(i-1,c,coins);return dfs(i-1,c,coins)+dfs(i,c-coins[i],coins);}int change(int amount, vector<int>& coins) {return dfs(coins.size()-1,amount,coins);}
};

2.记忆化搜索

还是老样子

初始化dp为-1,如果不是-1说明计算过了直接返回

并且在返回之前给dp赋值

class Solution {
public:int dfs(int i,int c,vector<int>& coins,vector<vector<int>>& dp){if(i<0)if(c==0)return 1;elsereturn 0;if(dp[i][c]!=-1)return dp[i][c];if(c<coins[i])return dp[i][c]=dfs(i-1,c,coins,dp);return dp[i][c]=dfs(i-1,c,coins,dp)+dfs(i,c-coins[i],coins,dp);}int change(int amount, vector<int>& coins) {vector<vector<int>> dp(coins.size(),vector<int>(amount+1,-1));return dfs(coins.size()-1,amount,coins,dp);}
};

3. 1:1翻译为动态规划

递归终止条件就是动态规划的初始化

i<0且c==0的时候就是返回1,而我们这里dp数组中的物品编号是从1开始的。所以,dp[0][0]就等于1。

(dp数组物品编号从0开始的太麻烦了就不写了),注意一点事dp数组中物品编号是从1开始的,而coins数组却是从0开始的

所以比较和加减coins[i]的地方都是coins[i-1]

因为dp数组中的第i个元素的重量在coins 的i-1的位置存储着

注意定义为unsigned,不然有个测试案例过不去

完整代码:

class Solution {
public:int change(int amount, vector<int>& coins) {vector<vector<unsigned>> dp(coins.size()+1,vector<unsigned>(amount+1,0));dp[0][0]=1;for(int i=1;i<=coins.size();i++)for(int j=0;j<=amount;j++)if(j<coins[i-1])dp[i][j]=dp[i-1][j];elsedp[i][j]=dp[i-1][j]+dp[i][j-coins[i-1]];return dp[coins.size()][amount];}
};

4.滚动数组优化

就是删掉第一维度就完事

从1开始

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

从0开始

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

遍历顺序先遍历背包容量后遍历物品和先遍历物品后背包容量

先遍历物品后遍历背包容量,求的是可以凑成target的组合

经典题目就是兑换零钱II

先背包容量后物品,求的是可以凑成target的排列

经典题目:
Day40 | 动态规划 :完全背包应用 组合总和IV(类比爬楼梯)-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/467540.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【DL】YOLO11 OBB目标检测 | 模型训练 | 推理

本文进行YOLO11的旋转目标检测任务,旋转目标检测能够更精确地定位和描述那些非水平排列的目标,比如倾斜的飞机、船舶等。在原始的目标检测中,添加一个角度预测,实现定向边界框检测。 话不多说,先来个效果图!!! YOLO11中的旋转目标检测的特点 ▲更精确的定位:通过使用…

自动泊车端到端算法 ParkingE2E 介绍

01 算法介绍 自主泊车是智能驾驶领域中的一项关键任务。传统的泊车算法通常使用基于规则的方案来实现。因为算法设计复杂&#xff0c;这些方法在复杂泊车场景中的有效性较低。 相比之下&#xff0c;基于神经网络的方法往往比基于规则的方法更加直观和多功能。通过收集大量专家…

2025斯诺克器材与用品展,2025郑州台球器材展会3月举办

立足中原&#xff0c;辐射全国&#xff0c;壹肆柒2025中国&#xff08;郑州&#xff09;国际台球产业博览会&#xff0c;展位招商正在进行&#xff1b; 2025中国&#xff08;郑州&#xff09;国际台球产业博览会&#xff08;壹肆柒台球展&#xff09; The 2025 China (Zhengzh…

单调栈—acwing

一、题目&#xff1a; AcWing 830. 单调栈 - AcWing 暴力算法思想 双指针算法&#xff0c;本质上是比较操作&#xff0c;两个循环&#xff0c;时间复杂度高。通过栈可以一次遍历。 可以知道&#xff0c;只要前面有一个小于我的数&#xff0c;就可以。如果前面的数&#xff…

Ingress nginx 公开TCP服务

文章目录 背景搞起拓展( PROXY Protocol )参考 背景 公司业务繁多&#xff0c; HTTP、GRPC、TCP多种协议服务并存&#xff0c;Kubernetes流量入口复杂&#xff0c;所以萌生了通过LoadBalancer Ingress-nginx 的方式完全的结果入口流量&#xff0c;当然在高并发的场景下可以对…

小白投资理财 - 看懂 MACA K线图

小白投资理财 - 看懂 MACA K线图 什么是 MACDMACD 主要有三种用法第一是看快线和慢线两个线的位置第二是观察两条线交叉的情况第三就是通过观察 BAR 柱状图可预判该股市的走向例子 MACD 缺点总结 股市茫茫大海, 打开 K 线图, 几时开始入场, 几时应该退场傻傻不知道,没有一个指标…

Essential Cell Biology -- Fifth Edition

今天开始看一本书&#xff0c;单纯想学生物和英语。如果有错误烦请大家指出。黑色下划线是总结&#xff0c; Chapter one 1.1 Cell: the fundamental units of life 什么是生物的基本特征&#xff0c;并将它们与非生物区分开来&#xff1f; 答案取决于[ hinges on]一个现在…

windows 实现 linux tail -f 的效果

需求&#xff1a; 有的环境部署在windows上面&#xff0c;想要查看生成的log日志&#xff0c;用文本打开无法实现自动更新&#xff0c;想要linux tail -f 的效果 编写txt文件 echo off powershell -Command "Get-Content -Path 文件地址 -Wait -Tail 200 -Encoding UTF8…

MySQL数据库专栏(四)MySQL数据库链接操作C#篇

摘要 主要讲述MySQL数据库链接操作C#的操作 目录 1、添加引用 2、接口介绍 2.1、MySqlConnection 2.2、MySqlCommand 2.3、MySqlDataReader 2.4、MySqlDataAdapter 2.5、MySqlTransaction 3、全网功能最全辅助类实现 4、辅助类调用实例 1、添加引用 …

tensorflow案例5--基于改进VGG16模型的马铃薯识别,准确率提升0.6%,计算量降低78.07%

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 本次采用VGG16模型进行预测&#xff0c;准确率达到了98.875&#xff0c;但是修改VGG16网络结构&#xff0c; 准确率达到了0.9969&#xff0c;并且计算量…

【MM-Align】学习基于输运的最优对齐动力学,快速准确地推断缺失模态序列

代码地址 - > github传送 abstract 现有的多模态任务主要针对完整的输入模态设置&#xff0c;即每个模态在训练集和测试集中要么是完整的&#xff0c;要么是完全缺失的。然而&#xff0c;随机缺失的情况仍然没有得到充分的研究。在本文中&#xff0c;我们提出了一种新的方…

github使用基础

要通过终端绑定GitHub账号并进行文件传输&#xff0c;你需要使用Git和SSH密钥来实现安全连接和操作。以下是一个基本流程&#xff1a; 设置GitHub和SSH 检查Git安装 通过终端输入以下命令查看是否安装Git&#xff1a; bash 复制代码 git --version配置Git用户名和邮箱 bash …

教程:FFmpeg结合GPU实现720p至4K视频转换

将一个 720p 的视频放大编码到 4K&#xff0c;这样的视频处理在很多业务场景中都会用到。很多视频社交、短视频、视频点播等应用&#xff0c;都会需要通过服务器来处理大量的视频编辑需求。 本文我们会探讨一下做这样的视频处理&#xff0c;最低的 GPU 指标应该是多少。利用开源…

大健康零售行业帮助中心的构建与客户服务优化

在大健康零售行业&#xff0c;客户服务的质量直接影响着企业的品牌形象和市场竞争力。随着数字化转型的推进&#xff0c;构建一个高效、智能的帮助中心成为了提升客户服务和满意度的关键。本文将分析大健康零售行业如何通过构建帮助中心来优化客户服务&#xff0c;并提升客户满…

想买开放式耳机如何挑选?5款高人气开放式耳机分享

很多人不知道的是&#xff0c;目前开放式耳机市场上&#xff0c;有90%的品牌都不是专业的开放式耳机品牌&#xff0c;跨界的大牌以及网红品牌占据了主流市场&#xff0c;这些品牌通常都是直接使用传统的声学技术直接应用在开放式耳机上&#xff0c;没有专门针对开放式环境的技术…

linux 通过apt安装软件包时出现依赖包版本不对的问题解决

通过网上查找解决办法时&#xff0c;发现的解决办法无法完美解决问题: 比如通过安装对应版本解决 如: sudo apt-get install xxx2.7.0ubuntu 这样会先卸载原先包&#xff0c;在安装对应版本的包 或者直接删除依赖的包 sudo apt-get purge xxxx 如果碰到底层包的话&#xf…

证件照尺寸168宽240高,如何手机自拍更换蓝底

在提供学籍照片及一些社会化考试报名时&#xff0c;会要求我们提供尺寸为168*240像素的电子版证件照&#xff0c;本文将介绍如何使用“报名电子照助手”&#xff0c;借助手机拍照功能完成证件照的拍摄和背景更换&#xff0c;特别是如何将照片尺寸调整为168像素宽和240像素高&am…

深度学习⑨GANs

Discriminative and Generative Models Deep learning中主要两种模型 判别模型专注于从输入预测输出,例如分类任务。学习数据点和标签之间的特征 生成模型则试图理解数据是如何产生的,能够生成新的数据样本。理解数据分布和是否可以被预测 Quiz time: Discriminative mo…

Hbase集群搭建

1. 环境 三台节点hadoop 集群zookeeper 集群hbase 1.1环境准备 使用前文hdfs三台节点 1.11 zookeeper搭建 下载 wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz解压 tar -zxvf apache-zookeeper-3.8.4-bin.tar.gz zookee…

jupyter notebook启动和单元格cell

一、jupyter notebook启动 1. 数据分析传统与进阶的区别 - 传统数据分析工具&#xff1a; 1. SPSS 2. EXCEL 3. POWERBI - 进阶数据分析&#xff1a;Python处理数据功能 1. 数据处理&#xff08;python处理数据功能&#xff09;coding 2. 富文…