前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >算法应对电商的各种满减活动

算法应对电商的各种满减活动

作者头像
JavaEdge
发布2023-01-11 11:24:03
5800
发布2023-01-11 11:24:03
举报
文章被收录于专栏:JavaEdge

动态规划roadmap

动态规划适于求解最优问题,如求最大值、最小值等。可显著降低时间复杂度,提高代码的执行效率。 难点和递归类似,求解问题的过程不太符合人类常规思维。

  • 本文会先通过两个非常经典的动态规划问题模型,展示动态规划存在的意义及动态规划解法是如何演化的,学会后即可举一反三。
  • 《动态规划理论》,我会总结动态规划适合解决的问题的特征,以及动态规划解题思路。除此之外,我还会将贪心、分治、回溯、动态规划这四种算法思想放在一起,对比分析它们各自的特点以及适用的场景
  • 《动态规划实战》,我会教你应用第二节讲的动态规划理论知识,实战解决三个非常经典的动态规划问题,加深你对理论的理解

经典案例

0-1背包

不同重量、不可分割的物品,选择一些装入背包。 在满足背包最大重量限制的前提下,求背包中物品总重量的max?

可用回溯穷举搜索所有可能的装法,然后找出最大值。但回溯算法时间复杂度太高,为指数级:

假设:

  • 背包最大承载重量9
  • 有5个不同物品
  • 每个物品重量2,2,4,6,3

回溯求解过程,用递归树:

每个节点表示一种状态(i, cw),如(2,2)决策第2个物品是否装入背包,在决策前,背包中物品的总重量是2。

发现有些子问题求解重复,如f(2, 2)和f(3,4)都被重复计算两次。 可借助“备忘录”,记录已计算好的f(i, cw),当再次计算到重复的f(i, cw)的时候,直接从备忘录中取出来用,避免冗余计算。

跟动态规划的执行效率基本无差。

把整个求解过程分为n个阶段:

  • 每个阶段会决策一个物品是否放到背包中
  • 每个物品决策(放入或者不放入背包)完后,背包中的物品的重量会有多种情况,即会达到多种不同的状态,对应到递归树中,就是不同节点。

把每层重复的状态(节点)合并,只记录不同状态,然后基于上一层状态集合,推导下一层状态集合。可通过合并每一层重复状态,保证每层不同状态的个数都不会超过w个(w表示背包的承载重量)。这就避免每层状态个数的指数级增长。

二维数组states[n][w+1],记录每层可达到的不同状态:

  • 第0个物品的重量是2,决策完后,对应背包两种状态,背包物品总重量0或2,即states[0][0]=truestates[0][2]=true
  • 第1个物品的重量也是2,基于之前背包状态,在这个物品决策完后,不同状态有3个,背包中物品总重量分别是0(0+0),2(0+2 or 2+0),4(2+2),即states[1][0]=truestates[1][2]=truestates[1][4]=true
  • 考察完所有物品后,states状态数组计算完毕

0表false,1表true,只需在最后一层,找一个值为true的最接近w(这里是9)的值,即背包中物品总重量的最大值。

动态规划这个名字的由来:把问题分解为多个阶段,每个阶段对应一个决策。记录每个阶段可达的状态集合(去掉重复的),然后通过当前阶段的状态集合,推导下一个阶段的状态集合,动态地往前推进。

实际上,只需一个大小为w+1 的一维数组。

0-1背包升级

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

依旧可回溯:

递归树中,每个节点表示一个状态。现在需3个变量(counter, currentWeight, currentValue)表示一个状态。

有几个节点的counter和currentWeight完全相同,如f(2,2,4)和f(2,2,3)。 背包物品总重量一样,f(2,2,4)这种状态对应物品总价值更大,可舍弃f(2,2,3)这种状态,只需沿着f(2,2,4)继续往下决策。

即对于(counter, currentWeight)相同的不同状态,只需保留cv最大的继续递归处理。

用回溯算法,就没法再用“备忘录”了。需换思路,动态规划是不是可以呢? 把整个求解过程分为n个阶段:

  • 每个阶段会决策一个物品是否放到背包中
  • 每个阶段决策完后,背包中的物品的总重量以及总价值,会有多种情况,即会达到多种不同的状态

用一个二维数组states[n][w+1],记录每层可达到的不同状态,当前状态对应最大总价值。 每层中(i, cw)重复的状态(节点)合并,只记录cv值最大的状态,然后基于这些状态来推导下一层的状态。

  • 时间复杂度是O(nw)
  • 空间复杂度也是O(nw) 空间复杂度也可优化

应对满减

凡电商,必有促销,如双十一最常见的“满200元减30元”促销活动。 现假设你的购物车有n个商品,希望从中选几个天命物品,凑足满减条件前提下,让选出的商品价格总和最大程度接近满减条件(200元),极限省钱。

要高效解决此类问题,就需动态规划(Dynamic Programming)。

类似0-1背包,只是“重量”换成了“价格”。

购物车中有n个商品。针对每个商品都决策是否购买。每次决策之后,对应不同的状态集合。 用一个二维数组states[n][x],记录每次决策之后所有可达的状态。

0-1背包找的是≤w的最大值,x就是背包的最大承载重量w+1。 现在要找的是≥200(满减条件)的值中最小的,所以不能设置为200+1。 若要购买的物品的总价格超过200太多,如1000,那这个羊毛“薅”得就没有太大意义了,可限定x值为1001。

不过,这个问题不仅要求≥200的总价格中的最小的,还要找出这个最小总价格对应都要购买哪些商品。可利用states数组,倒推出这个被选择的商品序列。

重点看后半部分,如何打印出选择购买哪些商品呢? 状态(i, j)只可能从

  • (i-1, j) states[i-1][j]==true,可达,说明没有购买第i个商品
  • (i-1, j-value[i]) states[i-1][j-value[i]]==true,说明购买了第i个商品。从中选择一个可达的状态(如果两个都可达,就随意选择一个),然后,继续迭代地考察其他商品是否有选择购买。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023/01/11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 动态规划roadmap
  • 经典案例
    • 0-1背包
    • 0-1背包升级
    • 应对满减
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档