40 _ 初识动态规划:如何巧妙解决“双十一”购物时的凑单问题?

news2024/11/18 4:37:28

淘宝的“双十一”购物节有各种促销活动,比如“满200元减50元”。假设你女朋友的购物车中有n个(n>100)想买的商品,她希望从里面选几个,在凑够满减条件的前提下,让选出来的商品价格总和最大程度地接近满减条件(200元),这样就可以极大限度地“薅羊毛”。作为程序员的你,能不能编个代码来帮她搞定呢?

要想高效地解决这个问题,就要用到我们今天讲的动态规划(Dynamic Programming)。

动态规划学习路线

动态规划比较适合用来求解最优问题,比如求最大值、最小值等等。它可以非常显著地降低时间复杂度,提高代码的执行效率。不过,它也是出了名的难学。它的主要学习难点跟递归类似,那就是,求解问题的过程不太符合人类常规的思维方式。对于新手来说,要想入门确实不容易。不过,等你掌握了之后,你会发现,实际上并没有想象中那么难。

为了让你更容易理解动态规划,我分了三节给你讲解。这三节分别是,初识动态规划、动态规划理论、动态规划实战。

第一节,我会通过两个非常经典的动态规划问题模型,向你展示我们为什么需要动态规划,以及动态规划解题方法是如何演化出来的。实际上,你只要掌握了这两个例子的解决思路,对于其他很多动态规划问题,你都可以套用类似的思路来解决。

第二节,我会总结动态规划适合解决的问题的特征,以及动态规划解题思路。除此之外,我还会将贪心、分治、回溯、动态规划这四种算法思想放在一起,对比分析它们各自的特点以及适用的场景。

第三节,我会教你应用第二节讲的动态规划理论知识,实战解决三个非常经典的动态规划问题,加深你对理论的理解。弄懂了这三节中的例子,对于动态规划这个知识点,你就算是入门了。

0-1背包问题

我在讲贪心算法、回溯算法的时候,多次讲到背包问题。今天,我们依旧拿这个问题来举例。

对于一组不同重量、不可分割的物品,我们需要选择一些装入背包,在满足背包最大重量限制的前提下,背包中物品总重量的最大值是多少呢?

关于这个问题,我们上一节讲了回溯的解决方法,也就是穷举搜索所有可能的装法,然后找出满足条件的最大值。不过,回溯算法的复杂度比较高,是指数级别的。那有没有什么规律,可以有效降低时间复杂度呢?我们一起来看看。

// 回溯算法实现。注意:我把输入的变量都定义成了成员变量。
private int maxW = Integer.MIN_VALUE; // 结果放到maxW中
private int[] weight = {
   22463};  // 物品重量
private int n = 5; // 物品个数
private int w = 9; // 背包承受的最大重量
public void f(int i, int cw) {
    // 调用f(0, 0)
  if (cw == w || i == n) {
    // cw==w表示装满了,i==n表示物品都考察完了
    if (cw > maxW) maxW = cw;
    return;
  }
  f(i+1, cw); // 选择不装第i个物品
  if (cw + weight[i] <= w) {
   
    f(i+1,cw + weight[i]); // 选择装第i个物品
  }
}

规律是不是不好找?那我们就举个例子、画个图看看。我们假设背包的最大承载重量是9。我们有5个不同的物品,每个物品的重量分别是2,2,4,6,3。如果我们把这个例子的回溯求解过程,用递归树画出来,就是下面这个样子:

递归树中的每个节点表示一种状态,我们用(i, cw)来表示。其中,i表示将要决策第几个物品是否装入背包,cw表示当前背包中物品的总重量。比如,(2,2)表示我们将要决策第2个物品是否装入背包,在决策前,背包中物品的总重量是2。

从递归树中,你应该能会发现,有些子问题的求解是重复的,比如图中f(2, 2)和f(3,4)都被重复计算了两次。我们可以借助递归那一节讲的“备忘录”的解决方式,记录已经计算好的f(i, cw),当再次计算到重复的f(i, cw)的时候,可以直接从备忘录中取出来用,就不用再递归计算了,这样就可以避免冗余计算。

private int maxW = Integer.MIN_VALUE; // 结果放到maxW中
private int[] weight = {2,2,4,6,3};  // 物品重量
private int n = 5; // 物品个数
private int w = 9; // 背包承受的最大重量
private boolean[][] mem = new boolean[5][10]; // 备忘录,默认值false
public void f(int i, int cw) { // 调用f(0, 0)
  if (cw == w || i == n) { // cw==w表示装满了,i==n表示物品都考察完了
    if (cw > maxW) maxW 

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

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

相关文章

【汇编】栈及栈操作的实现

文章目录 前言一、栈是什么&#xff1f;二、栈的特点三、栈操作四、8086cpu操作栈4.1 汇编指令4.2 汇编代码讲解问题&#xff1a;回答&#xff1a; 4.3 栈的操作4.3 push 指令和pop指令的执行过程执行入栈(push)时&#xff0c;栈顶超出栈空间执行出栈(pop)时&#xff0c;栈顶超…

Bert浅谈

优点 首先&#xff0c;bert的创新点在于利用了双向transformer&#xff0c;这就跟openai的gpt有区别&#xff0c;gpt是采用单向的transformer&#xff0c;而作者认为双向transformer更能够融合上下文的信息。这里双向和单向的区别在于&#xff0c;单向只跟当前位置之前的tocke…

【小收获】数组在声明时整体赋值的细节

在C中&#xff0c;在全局区声明的数组会自动初始化 如果没有为全局区的整数类型的数组指定初始值&#xff0c;那么它的元素都会被自动初始化为0。该特性适用于所有整数类型的数组&#xff0c;包括char、short、int、long等。&#xff08;注:char类型数组自动初始化为0&#xff…

CCF ChinaSoft 2023 论坛巡礼 | CCF-华为胡杨林基金-软件工程专项(海报)论坛

2023年CCF中国软件大会&#xff08;CCF ChinaSoft 2023&#xff09;由CCF主办&#xff0c;CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办&#xff0c;将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…

MySQL数据库——存储过程-游标(介绍-声明游标、打开游标、获取游标记录、关闭游标,案例)

目录 介绍 声明游标 打开游标 获取游标记录 关闭游标 案例 介绍 游标&#xff08;CURSOR&#xff09;是用来存储查询结果集的数据类型 , 在存储过程和函数中可以使用游标对结果集进行循环的处理。 游标的使用包括游标的声明、OPEN、FETCH 和 CLOSE&#xff0c;其语法…

机器学习第8天:线性SVM分类

文章目录 介绍 特征缩放 示例代码 硬间隔与软间隔分类 主要代码 代码解释 结语 介绍 作用&#xff1a;判别种类 原理&#xff1a;找出一个决策边界&#xff0c;判断数据所处区域来识别种类 简单介绍一下SVM分类的思想&#xff0c;我们看下面这张图&#xff0c;两种分类都…

第六十二周周报

学习目标&#xff1a; 一、实验 二、论文 学习时间&#xff1a; 2023.11.11-2023.11.17 学习产出&#xff1a; 实验 1、CB模块实验效果出来了&#xff0c;加上去效果不太行&#xff0c;后续实验考虑是否将CB模块换到其他地方 2、CiFAR100实验已完成&#xff0c;效果比Vi…

Unity 场景烘培 ——LensFlare镜头光晕(三)

提示&#xff1a;文章有错误的地方&#xff0c;还望诸位大神指出&#xff01; 文章目录 前言一、镜头光晕 (Lens Flares)是什么&#xff1f;二、使用Lens Flares组件总结 前言 一般情况下都会忽略的东西&#xff0c;镜头光晕。理论上不加镜头光晕&#xff0c;也不会有什么影响…

Pandas 累计统计函数【cumsum、cumprod、cummax、cummin】【计算前1/2/3/…/n个数的和、积、最大值、最小值】

一、累计统计函数 函数作用cumsum计算前1/2/3/…/n个数的和cummax计算前1/2/3/…/n个数的最大值cummin计算前1/2/3/…/n个数的最小值cumprod计算前1/2/3/…/n个数的积 import numpy as np import pandas as pd# np.nan &#xff1a;空值 df pd.DataFrame({key1: np.arange(1…

LoRa知识点记录

CFO(Central Frequency Offset):&#xff1a;不同设备之间的硬件缺陷引起的&#xff0c;会造成bin 偏移。CFO 引起的 bin 偏移对于preamble和data symbol 都是相同的。 我们在FFT之前应用汉明窗口来抑制旁瓣的影响 lora的灵敏度依赖于峰值高度 没有零填充会导致峰值高度不稳定 …

什么是NoSQL?什么是redis?redis是做什么的?

redis官网 NoSQL泛指非关系型数据库&#xff0c;redis是其中的一种&#xff0c;Redis是发展最快的。 什么是NoSQL&#xff1f; NoSQL是一个广义的术语&#xff0c;指的是非关系型数据库&#xff0c;不同于传统的关系型数据库&#xff08;如MySQL、Oracle等&#xff09;。它没有…

反转链表(图解)

LCR 024. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定单链表的头节点 head &#xff0c;请反转链表&#xff0c;并返回反转后的链表的头节点。 样例输入 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&…

Spring 如何自己创建一个IOC 容器

IOC(Inversion of Control),意思是控制反转&#xff0c;不是什么技术&#xff0c;而是一种设计思想&#xff0c;IOC意味着将你设计好的对象交给容器控制&#xff0c;而不是传统的在你的对象内部直接控制。 在传统的程序设计中&#xff0c;我们直接在对象内部通过new进行对象创建…

基础课6——开放领域对话系统架构

开放领域对话系统是指针对非特定领域或行业的对话系统&#xff0c;它可以与用户进行自由的对话&#xff0c;不受特定领域或行业的知识和规则的限制。开放领域对话系统需要具备更广泛的语言理解和生成能力&#xff0c;以便与用户进行自然、流畅的对话。 与垂直领域对话系统相比…

ChatGPT + DALL·E 3

参考链接&#xff1a; https://chat.xutongbao.top/

excel怎么能锁住行 和/或 列的自增长,保证粘贴公式的时候不自增长或者只有部分自增长

例如在C4单元格中输入了公式&#xff1a; 现在如果把C4拷贝到C5&#xff0c;D3会自增长为D4&#xff1a; 现在如果想拷贝的时候不自增长&#xff0c;可以先把光标放到C4单元格&#xff0c;然后按F4键&#xff0c;行和列的前面加上了$符号&#xff0c;锁定了&#xff1a; …

竞赛 题目:基于大数据的用户画像分析系统 数据分析 开题

文章目录 1 前言2 用户画像分析概述2.1 用户画像构建的相关技术2.2 标签体系2.3 标签优先级 3 实站 - 百货商场用户画像描述与价值分析3.1 数据格式3.2 数据预处理3.3 会员年龄构成3.4 订单占比 消费画像3.5 季度偏好画像3.6 会员用户画像与特征3.6.1 构建会员用户业务特征标签…

一文了解ChatGPT Plus如何完成论文写作和AI绘图

2023年我们进入了AI2.0时代。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车&#xff0c;就有可能被淘汰在这个数字化时代&#xff0c;如何能高效地处理文本、文献查阅、PPT…

SSL证书哪个品牌最好用?

现在市面上的SSL证书品牌有很多&#xff0c;选购SSL证书时有很多人并不是很清楚&#xff0c;因此有很多伙伴对于选择哪个SSL证书品牌而感到疑惑。今天JoySSL小编就专门介绍下哪些比较好用的SSL证书品牌。 SSL证书兼容性主要包含操作系统、浏览器、服务器三个方面&#xff0c;好…

SpringBoot-过滤器Filter+JWT令牌实现登录验证

登录校验-Filter 分析 过滤器Filter的快速入门以及使用细节我们已经介绍完了&#xff0c;接下来最后一步&#xff0c;我们需要使用过滤器Filter来完成案例当中的登录校验功能。 我们先来回顾下前面分析过的登录校验的基本流程&#xff1a; 要进入到后台管理系统&#xff0c;我…