代码随想录算法训练营day44

题目:322. 零钱兑换、279.完全平方数、139.单词拆分、多重背包

参考链接:代码随想录

322. 零钱兑换

思路:本题同样可以用完全背包问题,背包容量即为amount,物品weight和value都为硬币coins,需要求的是装满背包需要的最少物品个数。dp五部曲;dp数组,dp[j]表示装满容量为j的背包需要的最少物品个数;递推公式,这里就要详细思考一下,因为本题的dp和之前求的方法数等不一样,先装物品i,如果能先装进去,则j-coin[i]的需要最少个数为dp[j-coin[i]],故此时dp[j]=dp[j-coin[i]]+1,由于本题求的是最少个数,故应该使用min;初始化,dp[0]为0,表示装满0最小个数为0,但由递推公式可以看出,后面的递推需要用到min,故其他dp应该全部初始化为INT_MAX,在实际代码中由于有+1操作,初始化为INT_MAX-1;遍历顺序,本题求的是最小个数,排列组合不影响,故物品容量谁先遍历都可以;举例略。时间复杂度O(n*amount)。

class Solution {
public:int coinChange(vector<int>& coins, int amount) {vector<int> dp(amount+1,INT_MAX-1);//后面有+1操作,确保不越界dp[0]=0;for(int i=0;i<coins.size();i++){for(int j=0;j<=amount;j++){if(coins[i]<=j){dp[j]=min(dp[j],dp[j-coins[i]]+1);}}}if(dp[amount]!=INT_MAX-1){return dp[amount];}else{return -1;}}
};

279.完全平方数

思路:本题即把n分解成多个完全平方数的和,也符合完全背包的模型,n即为背包容量,weight和value都为各个完全平方数[1,4,9,16…],需要求的是最少数量,思路和上题类似。dp五部曲:dp数组,dp[j]表示j背分解为完全平方数之和的最小个数;递推公式,如果能先放进去物品i,dp[j]=min(dp[j],dp[j-nums[i]]+1);初始化,dp[0]=0,其他初始化为最大值;遍历顺序,本题求的最小个数,遍历顺序任意;举例略。时间复杂度O(n*√n),因为完全平方数不会超过n。

class Solution {
public:int numSquares(int n) {vector<int> dp(n+1,INT_MAX-1);dp[0]=0;for(int i=1;i<=int(sqrt(n));i++){//从1开始,到√n结束for(int j=0;j<=n;j++){if(i*i<=j){dp[j]=min(dp[j],dp[j-i*i]+1);}}}return dp[n];}
};

139.单词拆分

思路:本题首先想到的是回溯法,即把s不断拆分,并判断拆分结果在不在字典中。这里需要用到记忆化递归的方式,即保存递归计算中的结果,减小时间复杂度。注意本题不需要求出每一种拆分,只需要返回bool值,故我们的backtracking可以返回bool值。回溯返回条件即拆分位置超过size,for循环即对确定start后开始拆分的位置进行循环,i从start一直到s.size()-1。如果不使用memory数组保存计算结果,则会有大量重复计算,memory数组用于保存backtracking从0~s.size()-1的计算结果,一开始全部初始化为true,一旦for循环没有返回true,则会返回true,此时修改memory数组为false,当进入backtracking时,检测memory的值,如果本来就是false,说明本个start值已经被计算过,直接返回false不用再重新计算了。时间复杂度n*O(2^n)。

class Solution {
public:bool backtracking(string &s,unordered_set<string> &wordSet,vector<bool> &memory,int start ){if(start>=s.size()){//这里写==也行return true;}if(!memory[start]){return false;//值已经被修改过,说明从start这里拆分是不可行的}for(int i=start;i<s.size();i++){string word=s.substr(start,i-start+1);//拆分,从start开始往后逐渐拆分if(wordSet.find(word)!=wordSet.end() && backtracking(s,wordSet,memory,i+1)){//如果本次拆分可以在字典中找到,且后续拆分也成功return true;}}memory[start]=false;//for循环完成,依旧没有返回truereturn false;}bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet(wordDict.begin(),wordDict.end());//单词可以重复使用,首先第一步就是把字典去重vector<bool> memory(s.size(),true);return backtracking(s,wordSet,memory,0);}
};

回溯法太久没用也忘记了许多,本题让我重新回顾了一下。
然后是dp法,本题可以使用完全背包的模板,背包容量即为字符串s,物品即为s的子串。dp五部曲:dp数组,本题的dp数组和之前的背包问题都不同,dp[j]表示字符串长度为j的s子串能否由字典中的单词组成,能则为true,否则为false;递推公式,i<j,当[i,j]范围内的子串在字典中时且dp[i]为true,则dp[j]也为true,这个递推公式也是参考的背包问题的思路,相当于尾部的子串能放入背包中;初始化,dp[0]表示空串能否由字典中元素组成,但本题中s非空,故没有空串的情况,根据递推公式,dp[0]必须为true,否则后面全为false,其他值初始化为false;遍历顺序,本题的字典中单词拼成s,是有顺序可言的,故实际上是排列问题,应该先遍历s字符串,后遍历wordSet;举例略。时间复杂度O(n^3),其中substr为O(n)复杂度。

class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet(wordDict.begin(),wordDict.end());vector<bool> dp(s.size()+1,false);dp[0]=true;for(int j=1;j<=s.size();j++){//从1开始for(int i=0;i<j;i++){string word=s.substr(i,j-i);//分割子串if(wordSet.find(word)!=wordSet.end() && dp[i]==true){dp[j]=true;}}}return dp[s.size()];}
};

多重背包

思路:多重背包问题,物品N,容量V,其中每个物品至多有Mi种,重量和价值都给定,求最大价值。多重背包和01背包的区别就是每个物品不止一个有给定数量,但是如果将其摊开来看,就是一个01背包问题。那么写代码的时候就是在01背包的基础上进行修改。但是我们不能直接把weight和value数组直接用新数组push_back,这样非常耗时,基本会超时。在写代码的时候需要把每种物品遍历的个数在01背包里再遍历一遍。对本题,dp五部曲:dp数组,dp[j]表示容量为j的背包能装的最大价值;递推公式,如果物品i能够先放进去,dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);初始化,全部初始化为0;遍历顺序,对容量反着来;举例略。时间复杂度O(mnk)。这个基本不会考。

#include<bits/stdc++.h>
using namespace std;int solve(int c,int n,vector<int> &weight,vector<int> &value,vector<int> &nums){vector<int> dp(c+1,0);for(int i=0;i<n;i++){for(int j=c;j>=0;j--){for(int k=1;k<=nums[i];k++){//遍历数量,对于给定的容量j和物品i,把物品的所有数量都考虑到if(k*weight[i]<=j){dp[j]=max(dp[j],dp[j-k*weight[i]]+k*value[i]);}}}}return dp[c];
}int main(){int c,n;while(cin >> c >> n){vector<int> weight(n,0);vector<int> value(n,0);vector<int> nums(n,0);for(int i=0;i<n;i++){cin >> weight[i];}for(int i=0;i<n;i++){cin >> value[i];}for(int i=0;i<n;i++){cin >> nums[i];}cout << solve(c,n,weight,value,nums) << endl;}return 0;
}

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

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

相关文章

Python使用ElementTree解析xml的方法

解析XML xml.etree.ElementTree是Python标准库中用于处理XML的模块 可以通过以下语句引入 import xml.etree.ElementTree as ET解析xml时&#xff0c;可以从文件中导入&#xff0c;也可以从string获取 例如&#xff1a; # 从字符串中导入 xml_string <root><eleme…

vue国际化(中英文切换)

思路&#xff1a; 构建了一个 VueI18n 的实例&#xff0c;明确了默认与备用语言及对应的语言包。在组件中获取组件实例以方便后续操作&#xff0c;设置一个点击事件实现语言切换并触发重新获取消息的动作&#xff0c;ref 创建的 msg 用于存储消息内容&#xff0c;设置一个函数…

C++学习(19)

#学习自用# 宏 当我们编译C文件时&#xff0c;首先预处理器会过一遍所有带# 的语句&#xff08;预编译指令符号&#xff09;&#xff0c;然后进行文本替换。 #include<iostream> using namespace std; #define SQUARE(X) X*Xint main() {int a SQUARE(5);cout <&…

linux-awk分析指令

目录 基本用法: 条件语句: 内置变量: 自定义分隔符: 数学运算: 使用多个文件: 生成“完整使用报告”的示例: 8. 模式匹配 9. BEGIN和END模式 10. 数组和关联数组 11. 脚本方式使用 12. 逐行处理 13. 控制语句 awk 是一个强大的文本处理工具&#xff0c;用于在文本…

路虽远,行则将至 - 附暑期实习、秋招历程经验分享

前言 大家好 许久没有时间静下心来打开编辑器写文章了 忙碌暂过&#xff0c;难得一闲时 求学三年&#xff0c;终到离别时 回忆过往&#xff0c;枯燥且多彩 有一点经验&#xff0c;以文字形式分享&#xff0c;希望帮助到大家 可能是这段时间事多且杂&#xff0c;加上很长一…

电脑桌面上用来记事的便签软件

便签软件已成为我们日常生活中不可或缺的记录工具。想象一下&#xff0c;在繁忙的工作中&#xff0c;你突然需要记下一个重要事项或临时想法&#xff0c;这时&#xff0c;一个便捷、高效的便签软件就显得尤为重要。它能帮助我们迅速捕捉信息&#xff0c;轻松管理琐碎事务&#…

LINUX 安装JAVA

安装上传下载 yum -y install lrzsz 建存放目录 mkdir /source mkdir /source/java 进入目录&#xff0c;拖拉上传JDK 解压 tar -zxvf jdk-8u261-linux-x64.tar.gz 配置 vi /etc/profile 在末尾添加以下配置 export JAVA_HOME/source/java/jdk1.8.0_261 export JRE…

通信设备的网卡

一、网卡的作用 将计算机或者路由器连接到传输介质上的接口&#xff0c;传输介质可以是有线也可以是无线的。 &#xff08;1&#xff09;计算机的网卡 现在的计算机大多有两个网卡&#xff0c;一个是有线网卡一个无线网卡&#xff0c;比如以我们的台式电脑为例 台式电脑千兆网…

【氵】Archlinux+KDE Plasma 6+Wayland 安装nvidia驱动 / 开启HDR

参考: NVIDIA - Arch Linux 中文维基 &#xff08;其实就是把 wiki 简化了一下 注&#xff1a;本教程适用 GeForce 930 起、10 系至 20 系、 Quadro / Tesla / Tegra K-系列以及更新的显卡&#xff08;NV110 以及更新的显卡家族&#xff09;&#xff0c;此处以 RTX3060 为例 …

Scikit-learn 基础教程:机器学习的初步指南

Scikit-learn 是一个用于数据挖掘和数据分析的机器学习库&#xff0c;建立在 NumPy、SciPy 和 matplotlib 之上。它提供了简单而高效的工具来进行数据分析和建模。本文将为您介绍 Scikit-learn 的安装方法、核心组件&#xff0c;以及如何应用这些组件进行一个简单的机器学习项目…

Pytorch--Convolution Layers

文章目录 1.nn.Conv1d2.torch.nn.Conv2d()3.torch.nn.ConvTranspose1d()3.torch.nn.ConvTranspose2d() 1.nn.Conv1d torch.nn.Conv1d() 是 PyTorch 中用于定义一维卷积层的类。一维卷积层常用于处理时间序列数据或具有一维结构的数据。 构造函数 torch.nn.Conv1d() 的语法如…

边缘计算(Edge Computing)_关键概念/优势/应用场景

边缘计算&#xff08;Edge Computing&#xff09;是一种计算范式&#xff0c;它将数据处理和分析从传统的集中式数据中心和云计算平台移至更接近数据生成源头的位置&#xff08;即“边缘”&#xff09;&#xff0c;例如物联网设备、传感器、路由器或其他边缘设备。边缘计算旨在…

vector迭代器失效

1.迭代器失效的根本原因 迭代器就是指针&#xff0c;迭代器失效就是指针失效。 指针失效的有两种情况&#xff1a; 1&#xff09;野指针 2&#xff09;访问越界 2.举例阐述 这段代码已经报错了&#xff0c;我给大家调试一下。可以发现&#xff1a;vector的容量变大了&…

C语言之main函数的返回值(在linux中执行shell脚本并且获取返回值)

一&#xff1a;函数为什么要返回值 &#xff08;1&#xff09;函数 在设计的时候是设计了参数和返回值&#xff0c;参数是函数的输入&#xff0c;返回值是函数的输出 &#xff08;2&#xff09;因为函数需要对外输出数据&#xff08;实际上是函数运行的一些结果值&#xff09;…

springbot 界面美观的超市收银管理系统。

springbot 界面美观的超市收银管理系统。 功能&#xff1a;登录&#xff0c;用户管理&#xff0c;权限菜单管理&#xff0c;首页订单&#xff0c;收入&#xff0c;用户统计&#xff0c; 收银台&#xff0c;销售账单&#xff0c;库存管理&#xff0c;商品分类&#xff0c;供应…

30 岁的程序员,要有 “归零“ 心态

大家好&#xff0c;我是码农先森。 古话说的 “三十而立”&#xff0c;正是担重之时&#xff0c;却大部分人在职场中都处于不上不下的尴尬境地。已经没有刚毕业时那股子冲劲&#xff0c;被生活和工作磨平了棱角。 在技术思想方面&#xff0c;似乎已经触及到了天花板&#xff…

嵌入式系统中判断大小端的方法与实现

第一&#xff1a;大小端基本分析 程序判断计算机是大端的还是小端的&#xff0c;判断的思路是确定一个多字节的值(下面使用的是4字节的整数)&#xff0c;将其写入内存(即赋值给一个变量)&#xff0c;然后用指针取其首地址所对应的字节(即低地址的一个字节)&#xff0c;判断该字…

shell循环以及实验

循环是一种重复执行的代码结构&#xff0c;只要满足循环的条件&#xff0c;会一直执行这个代码 循环条件&#xff1a;在一定范围之内&#xff0c;按照指定次数来执行循环。 循环体&#xff1a;在指定的次数内&#xff0c;执行的命令序列&#xff0c;只要条件满足&#xff0c;…

C#知识|模块化分层学习笔记

哈喽&#xff0c;你好&#xff0c;我是雷工&#xff01; 01 基本分层 典型的两层结构&#xff1a;由UI层 数据访问层 实体类构成。 其中实体类不算一层&#xff0c;本质是一个数据载体。 02 模块化分层 模块概念&#xff1a;在.NET平台中&#xff0c;模块主要是指类库项目。…

Mac下载了docker,在终端使用docker命令时用不了

问题&#xff1a;在mac使用docker的时候&#xff0c;拉取docker镜像失败 原因&#xff1a;docker是需要用app使用的 &#xff0c;所以在使用的时候必须打开这个桌面端软件才可以在终端上使用docker命令&#xff01;&#xff01;&#xff01;