算法 DAY45 动态规划07 70. 爬楼梯 322. 零钱兑换 279. 完全平方数 139. 单词拆分 多重背包

news2024/10/1 3:22:39

70. 爬楼梯

和377. 组合总和 Ⅳ (opens new window)基本就是一道题了。本题代码不长,题目也很普通,但稍稍一进阶就可以考察完全背包

class Solution {
public:
    int climbStairs(int n) {
        vector<int> nums = {1,2};
        vector<int> dp(n+1,0);
        dp[0] = 1;
        for(int j = 0; j <=n; j++){
            for(int i = 0; i < nums.size(); i++){
                if(j >= nums[i]) dp[j] += dp[j - nums[i]];
            }
        }
        return dp[n];
    }
};

322. 零钱兑换

动态规划五部曲
1、确定dp[j]的含义
dp[j] 凑成 j 的最少硬币的个数
2、确定递推公式
比如想凑成3,
如果手里有1,那么最小个数就是dp[2]+1
如果手里有2,那么最小个数就是dp[1]+1
如果手里有3,那么最小个数就是dp[0]+1
dp[j] = min(dp[j] , dp[j-nums[i]] + 1)
3、确定初始值
dp[0] = 0
其余值应给 INT_MAX。
最终dp[j] == INT_MAX 就返回-1
4、确定遍历顺序
首先这是个完全背包,背包容量从小到大遍历。其次,{5,5,1} 和{1,5,1}的组合大小都是3,所以两层for循环无所谓遍历顺序。
5、验证
coins = [1, 2, 5], amount = 11

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

279. 完全平方数

1、dp[j] : 构成 j 的完全平方数的最小数量
2、dp[j] = min( dp[j] , dp[j - i * i ] + 1)
3、初始化
1 <= n <= 104,所以dp[0]无意义
dp[1] = 1, 其余值给INT_MAX
4、完全背包,求个数所以不用管两个for的内外

class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n+1,INT_MAX);
        dp[0] = 0;
        dp[1] = 1;
       
        for(int i = 1; i <= n ; ++i){
            for(int j = i*i; j <= n; ++j){
                if(dp[j-i*i] != INT_MAX) dp[j] = min(dp[j], dp[j - i*i] + 1);
            }
        }
        return dp[n] ;
    }
};

139. 单词拆分

本题与回溯中:分割回文子串的思路是一样的,通过分割字符串,得到单词,再去单词列表中寻找该单词是否存在。
回溯写法:
其中的memory数组,与之前组合问题中的去重数组作用一致。本题中通过在对应的位置设置false,来标记该字母后的字符串没有可分割的方法。例如:
cat sand og,在index = 7的地方设置false(og),
cats and og,当再一次分割到index = 7的时候,就不再进入for循环判断og有无合适的分割方法,而是直接通过memory[7] = false 返回false。
时间复杂度还是O(2n),但是比没有memory数组的情况好很多。

namespace jj22 {
	class Solution {
	public:
		bool wordBreak(string s, vector<string>& wordDict) {
			unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
			vector<bool> memory(s.size(), 1); // -1 表示初始化状态
			return backtracking(s, wordSet, 0,memory);
		}
		bool backtracking(string s,unordered_set<string>& wordSet,int startIndex, vector<bool>& memory) {
			if (startIndex >= s.size())return true;
			if (!memory[startIndex]) return memory[startIndex];
			for (int i = startIndex; i < s.size(); ++i) {
				string word = s.substr(startIndex, i - startIndex + 1);
				if (wordSet.find(word) != wordSet.end() && backtracking(s, wordSet, i + 1,memory)) {
					return true;
				}
			}
			memory[startIndex] = false; // 记录以startIndex开始的子串是不可以被拆分的
			return false;
		}

	};
	void test() {
		string s = "catsandog";
		vector<string> wordDict = { "cats", "dog", "sand", "and", "cat" };
		Solution ss;
		bool temp = ss.wordBreak(s, wordDict);
		int a = 10;
	}
}

背包解法:
首先,本题的物品就是各个单词,背包容量是字符串长度。由于物品可以重复拿取,所以是完全背包问题。
五部曲:
1、dp数组的含义
dp[j] : 长度为j 的字符串能否被单词列表里的单词组成
2、递推公式
当 i < j 时,如果dp[i] = true(即 dp[i] 长度为 i 的字符串能否被单词列表里的单词组成),
并且 i+1 到 j 组成的单词在列表中能找到,则dp[j] = true
3、初始化
dp[0] = true
其余为false
例如:

string s = "catsandog";
vector<string> wordDict = { "cats", "dog", "sand", "and", "cat" };

dp[2] , j = 2, i = 0时,0-2的cat可以被找到,并且依赖于dp[0],所以dp[0] 必须为true
4、遍历顺序
构成字符串的单词顺序是唯一的,所以是求排列问题,{1,5}和{5,1}是两种不同的答案。
所以外层遍历背包,内层遍历物品。
5、举例推导dp[i]
在这里插入图片描述自己写的:内层遍历直接就是单词列表


	class Solution {
	public:
		bool wordBreak(string s, vector<string>& wordDict) {
			vector<bool> dp(s.size() + 1, 0);
			dp[0] = true;
			for (int j = 0; j <= s.size(); ++j) {
				for (int i = 0; i < wordDict.size(); ++i) {
					string temp = wordDict[i];
					if (j >= temp.size() && dp[j - temp.size()] == true && s.substr(j - temp.size(), temp.size()) == temp) dp[j] = true;
				}
			}
			return dp[s.size()];
		}

	};

卡哥写的:内层是在从0开始遍历字符串,到 j 。看i-j组成的单词能否被找到

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 i = 1; i <= s.size(); i++) {   // 遍历背包
            for (int j = 0; j < i; j++) {       // 遍历物品
                string word = s.substr(j, i - j); //substr(起始位置,截取的个数)
                if (wordSet.find(word) != wordSet.end() && dp[j]) {
                    dp[i] = true;
                }
            }
        }
        return dp[s.size()];
    }
};

多重背包理论基础

每件物品最多有Mi件可用,把Mi件摊开,其实就是一个01背包问题了。
例如:

背包最大重量为10。

物品为:
重量 价值 数量
物品0 1 15 2
物品1 3 20 3
物品2 4 30 2

问背包能背的物品最大价值是多少?

和如下情况有区别么?
重量 价值 数量
物品0 1 15 1
物品0 1 15 1
物品1 3 20 1
物品1 3 20 1
物品1 3 20 1
物品2 4 30 1
物品2 4 30 1

毫无区别,这就转成了一个01背包问题了,且每个物品只用一次。

void test_multi_pack() {
    vector<int> weight = {1, 3, 4};
    vector<int> value = {15, 20, 30};
    vector<int> nums = {2, 3, 2};
    int bagWeight = 10;
    for (int i = 0; i < nums.size(); i++) {
        while (nums[i] > 1) { // nums[i]保留到1,把其他物品都展开
            weight.push_back(weight[i]);
            value.push_back(value[i]);
            nums[i]--;
        }
    }

    vector<int> dp(bagWeight + 1, 0);
    for(int i = 0; i < weight.size(); i++) { // 遍历物品
        for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
            dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
        }
        for (int j = 0; j <= bagWeight; j++) {
            cout << dp[j] << " ";
        }
        cout << endl;
    }
    cout << dp[bagWeight] << endl;

}

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

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

相关文章

while语句和until语句顺便带点小实验

while语句和until语句 一、while用法二、Until循环语句三、趣味小实验猜价格的游戏&#xff08;价格是随机数&#xff09;写一个计算器脚本闲来无事去购物 一、while用法 for循环语句非常适用于列表对象无规律&#xff0c;且列表来源以固定&#xff08;如某个列表文件&#xf…

Android Studio开发图书管理系统APP

Android Studio开发项目图书管理系统项目视频展示&#xff1a; 点击进入图书管理系统项目视频 引 言 现在是一个信息高度发达的时代&#xff0c;伴随着科技的进步&#xff0c;文化的汲取&#xff0c;人们对于图书信息的了解与掌握也达到了一定的高度。尤其是学生对于知识的渴…

word构建基块:快速插入重复内容的高级剪切板

本文参考自 word录入技巧&#xff1a;如何用自动图文集快速插入重复内容 - 知乎 介绍 构建基块&#xff0c;它就是和剪切板一样&#xff0c;点一下就粘贴一份新的&#xff0c;用于解决大量重复内容的复制粘贴 构建基块包括自动图文集和快速表格&#xff0c;实际上都是构建基块…

Blender启动场景的修改

Blender启动场景的修改 1 使用版本2 现象描述3 解决方法4 启动场景路径5 清理场景资源5.1 空场景大小5.2 清理图片资源5.2.1 断开数据块关联5.2.2 断开伪用户关联5.2.3 断开多用户关联5.2.4 清理数据块5.2.6 文件校验 5.3 使用自建资源库 6 数据块类型 1 使用版本 Blender 3.3…

二叉树建立、遍历、打印(23春教学)

#include<stdio.h> #include <malloc.h> #include <conio.h> typedef char DataType; typedef struct Node {DataType data;struct Node *LChild;struct Node *RChild; }BitNode,*BitTree; void CreatBiTree(BitTree *bt)//用扩展先序遍历序列创建二叉树&am…

《LearnUE——基础指南:上篇—3》——GamePlay架构WorldContext,GameInstance,Engine之间的关系

目录 平行世界是真实存在的吗&#xff1f; 1.3.1 引言 1.3.2 世界管理局&#xff08;WorldContext&#xff09; 1.3.3 司法天神&#xff08;GameInstance&#xff09; 1.3.4 上帝&#xff08;Engine&#xff09; 1.4 总结 平行世界是真实存在的吗&#xff1f; 1.3.1 引言 …

DAY 51 LVS负载均衡——DR模式

数据包流向分析 &#xff08;1&#xff09;客户端发送请求到Director Server (负载均衡器)&#xff0c;请求的数据报文&#xff08;源IP是CIP&#xff0c;目标IP是VIP&#xff09;到达内核空间。 &#xff08;2&#xff09;Director Server 和Real Server 在同一个网络中&…

【五一创作】ERP实施-委外业务-委外采购业务

委外业务主要有两种业务形态&#xff1a;委外采购和工序外协&#xff0c;委外采购主要是在MM模块中实现&#xff0c;工序外协主要由PP模块实现&#xff0c;工序外协中的采购订单创建和采购收货由MM模块实现。 委外采购概念 委外采购&#xff0c;有些企业也称为带料委外或者分包…

【Spring框架全系列】方法注解@Bean的使用

&#x1f4ec;&#x1f4ec;哈喽&#xff0c;大家好&#xff0c;我是小浪。上篇博客我们介绍了五大类注解的使用方法&#xff0c;以及如何解决Spring使用五大类注解生成bean-Name的问题&#xff1b;那么&#xff0c;谈到如何更简单的读取和存储对象&#xff0c;这里我们还需要介…

如何防止系统发生异常时,别人传递过来的关键数据不丢失?(AOP + xxlJob)

需求 在开发中&#xff0c;客户每天需要定时调用我们的api去上传一些数据到数据库中&#xff0c;当数据库发生异常或者系统发生异常&#xff0c;上传的一些数据会丢失不做入库操作&#xff0c;现想防止数据库或系统发生异常&#xff0c;数据能不丢失&#xff0c;同时&#xff…

TryHackMe-AD证书模板

AD Certificate Templates SpecterOps 完成并作为白皮书发布的研究表明&#xff0c;可以利用配置错误的证书模板进行权限提升和横向移动。根据错误配置的严重性&#xff0c;它可能允许 AD 域上的任何低特权用户只需单击几下即可将其权限提升为企业域管理员的权限&#xff01; …

C语言宏使用

C语言宏 编译一个C语言程序的第一步骤就是预处理阶段&#xff0c;这一阶段就是宏发挥作用的阶段,编译完之后宏对二进制代码不可见。 使用 1. 宏常量 #define PI 3.142. 宏语句 #define Print printf("hello,world!\r\n")3. 宏函数 使用宏来定义函数&#xff0c…

基于灰狼算法的极限学习机(ELM)回归预测-附代码

基于灰狼算法的极限学习机(ELM)回归预测 文章目录 基于灰狼算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于灰狼算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;本文利用灰狼算法对极限学习机进行优化&#xff0c;并…

[stable-diffusion-art] 指北-3 inpainting

https://stable-diffusion-art.com/inpainting_basics/https://stable-diffusion-art.com/inpainting_basics/inpainting的应用主要是重绘&#xff0c;目前的模型换衣主要还是通过lora训练特定衣服来实现的。 模型权重&#xff1a; !wget https://huggingface.co/runwayml/sta…

一、spring Cloud Alibaba概述

spring Cloud Alibaba学习&#xff0c;第一篇spring Cloud Alibaba概述篇。 微服务是一种架构思想&#xff0c;spring Cloud Alibaba是微服务的系列化实现方式之一。 一、架构演变过程 架构粒度更加精细&#xff0c;拆分成不同的服务&#xff0c;每个服务直接互不影响&#…

基于海鸥算法的极限学习机(ELM)回归预测-附代码

基于海鸥算法的极限学习机(ELM)回归预测 文章目录 基于海鸥算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于海鸥算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;本文利用海鸥算法对极限学习机进行优化&#xff0c;并…

【LeetCode股票买卖系列:309. 最佳买卖股票时机含冷冻期 | 暴力递归=>记忆化搜索=>动态规划】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

C/C++笔记-分析带有Q_OBJECT继承QObject的类make流程

此篇博文记录到个笔记时间2023-02-15&#xff0c;发表到网上的时间是2023-05-03。 这里以Qt5.5.1为例&#xff0c;操作系统是centos 7.5版本。 代码如下&#xff1a; MOCQtConsole.pro QT coreTARGET MOCQtConsoleSOURCES main.cpp \Test.cppHEADERS Test.hTest.h …

Threejs进阶之十二:Threejs与Tween.js结合创建动画

tween.js介绍 Tween.js是一个可以产生平滑动画效果的js库&#xff0c;其官方地址为&#xff1a;https://github.com/tweenjs/tween.js/&#xff0c;可以将源码下载后&#xff0c;可以在tween.js/dist/文件夹下找到相应的js代码&#xff0c;在HTML中进行引用&#xff1b;也可以…

配置KylinV10

配置KylinV10 文章目录 配置KylinV10设置“root”登录密码允许通过图像界面登录到“root”开机自动登录到“root”关闭“麒麟安全授权认证”关闭自动睡眠挂载“Windows”下共享目录到虚拟机安装“Docker”到“KylinV10”B/S安装“Maven-3.6.3”安装“Gradle-4.4.1”安装“Jdk-8…