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

回溯法

我们假设购物满w元才能减。例如满500减200,那w=500。购物车中商品的价格int[] price表示。每次决定第i个物品要不要购买,当物品选完了或者总价够w,停止选择。比较选中物品价格总和最低的一组选择。这是一个多阶段决策最优化问题。可以先用回溯算法解决。

public class Shopping {private int[] price = new int[]{198,201,345,200};private int w = 500;private int minPrice = Integer.MAX_VALUE;private List<Integer> selectItems;private void f (int i,int priceSum,boolean[] shoppingStatus){if(priceSum>w){if(priceSum<minPrice){minPrice = priceSum;selectItems = new ArrayList<Integer>();for(int j=0;j<shoppingStatus.length;j++){if(shoppingStatus[j]){selectItems.add(j);}}}return;}if(i==price.length) return;shoppingStatus[i] = true;f(i+1,priceSum+price[i],shoppingStatus);//选择第i件商品shoppingStatus[i] = false;f(i+1,priceSum,shoppingStatus);//不选择第i件商品}public void decision(){boolean[] shoppingStatus = new boolean[price.length];f(0,0,shoppingStatus);}
}

递归树

递归树中的每个节点是一个状态,用(i,preSum)表示。i表示将要处理第i个商品。preSum表示当前状态下已经购买商品的价格和。可以看到这里的状态表示的参数基本和f函数的参数是相同的。
在这个例子中,(i,preSum)相同的节点正好都只有一个,但不排除有多个节点的可能性。

状态表

根据(i,preSum)我们知道用一个二维表可以表示各种不同的状态。第一维(行)是商品下标,第二维(列)是商品总价。又因为题目要求价格和需要大于w,但我们又不能让商品和太大,太大优惠就没有必要了。我们需要给商品总价一个最大值3w。

状态表boolean[][] states。
第0个商品决策之后,states[0][0]=true;states[0][198]=true。
第1个商品决策之后,states[1][0]=true;states[1][201]=true;states[1][198]=true;states[1][399]=true;

我们在states[n-1]从下标w开始找值为true的元素下标。最先找到的就是符合要求的最小价格。
它与莱文斯坦距离、矩阵中的最短路径长度不同的地方是,不需要在每一步决策之后只保留最小值,其他节点放弃。
我想这里没有放弃其他节点,是因为这里的每一个状态可能就是最终答案。第i个商品是不是购买,和第i-1个商品决策之后的所有状态有关系。

 public void decisionDp(){int n = price.length;int maxw = 3*w;boolean[][] states = new boolean[n][maxw+1];states[0][0] = true;if(price[0]<maxw){states[0][price[0]] = true;}for(int i=1;i<n;i++){//不购买第i个for(int j=0;j<maxw+1;j++){if(states[i-1][j]){states[i][j] = true;}}//购买第i个for(int j = 0;j<maxw+1;j++){if(states[i-1][j]==true && j+price[i]<maxw){states[i][j+price[i]] = true;}}}int minPrice = -1;for(int j = w;j<maxw+1;j++){if(states[n-1][j]){minPrice = j;break;}}//说明有选择if(minPrice!=-1){System.out.println(minPrice);int j = minPrice;for(int i=n-1;i>=1;i--){if(j-price[i]>=0 && states[i-1][j-price[i]]){System.out.println(price[i]);//购买这件商品}}if(j!=0){System.out.println(price[0]);}}}

当然,这道题目还要一个难点是要输出选择了哪些商品。当我们知道满足要求的最低总价是minPrice。也就是说states[n-1][minPrice]=true。如果states[n-2][minPrice]=true,则说明第n-1号物品是被放弃的,不购买的。如果states[n-2][minPrice-price[n-1]]=true,说明是购买第n-1号商品的。继续递归往回查找。

动态规划——双11既可以薅羊毛还能花钱最少相关推荐

  1. 双11来了,你还在狂补数学么?

    先分享个旧视频吧,就当周末放松看看也好. 前几年在新加坡,有个朋友说回老家农村,家里的电视很旧了,不忍心,提出换个新的,家里老奶奶说等等,等双11再换.对方表示很震惊,想不到在中国农村的老年人,都已经 ...

  2. <第5个月>运营日记,第一次经历双11,2020年shopee还值不值得做

    这是本周的数据,单周的哈,单量比之前多是因为双11带起来的,今天着重说下双11. 看下双11当天的情况吧 一般每逢大促我这边订单会翻倍,最近阶段每天20单,我估算了一下双十一起码翻三倍吧,所以定了个目 ...

  3. 双11史上作业数最多,人工干预最少的一次技术保障

    引言 阿里巴巴双11史上作业数最多,但人工干预最少的一次双11技术保障: 从动态并发调整带来的单日10亿计算节点的节省,到数据智能编排带来的高级基线单个作业数十个小时执行时间的缩短,再到全新Bubbl ...

  4. 动态规划应用--双11购物凑单

    文章目录 1. 问题描述 2. 代码实现 1. 问题描述 双11购物节的时候,某宝给你很多张满300减50的优惠券,你想组合各种商品的价格总和>=300,且金额总和越接近300越好,这样可以多薅 ...

  5. 从双11看技术趋势:金融行业总动员之阿里金融云

    刚刚结束的天猫双11,让全世界震撼的不只是逆天的销售额,还有深不可见的科技力量. 在这场全球共振的狂欢中,阿里巴巴展现了从一家电商公司转型到一家以技术为驱动的科技公司的深刻转变.阿里巴巴的支付.物流. ...

  6. 全球顶级设计师云集天猫双11 超1000款时尚大牌新品首发

    什么样的秀场能实现超过千款新品的现场展示.即时售卖?还要接受数亿挑剔的消费者的随时点评和PK? 答案是天猫. 10月20日,在第十年的天猫双11宣布启动之际,天猫也为全球顶尖品牌们在北京地标建筑水立方 ...

  7. 双11电商手机大战盘点,大神荣耀各成势力

    今年的双11虽然已经落下帷幕,但它带来的网购热情还在延续.可以预见,在未来的一周内,双11网购的各种话题还将持续. 11月12日凌晨00:04,@雷军即在微博宣布了@小米手机的双11战果:" ...

  8. 突然!iPhone 12/12 Pro从苹果天猫旗舰店下架,不愿参加双11活动?

    今天上午,有不少网友发现,苹果天猫旗舰店的iPhone 12和iPhone 12 Pro被下架了. 经验证,Apple Store天猫官方旗舰店商品页面显示, iPhone 12与iPhone 12 ...

  9. 今年天猫双11的这些技术,可能会改变整个零售行业

    零售行业的"春晚"天猫双11于20日在香港揭幕,我有幸赶赴现场,见证了一场别开生面的启动仪式:启德码头.醒狮点睛.模拟飞行-之所以在形式上大费周章,用阿里巴巴CEO.一手缔造天猫的 ...

最新文章

  1. Spring Cloud Gateway重试机制
  2. dir在python中什么意思_python中dir是什么
  3. 应该知道的自动化测试陷阱2
  4. 个子矮s弯如何看点打方向图解_S弯如何看点打方向
  5. 通达oa wbupload.php,关于通达OA上传附件类型限制的设置
  6. escilpe mysql,wordpress函数esc_sql()用法示例
  7. java char数组查找_我爱java系列---【在字符数组中查询某个字符串是否存在】
  8. Mybatis plus修改了Language Level后,IDEA运行应用出现了Information:java: javacTask: 源发行版 8 需要目标发行版 1.8
  9. Go没有枚举类型(enums),用const常量的iota替代
  10. 机器人赛文_动漫中机器人赛文与真正的赛文奥特曼相比,谁更厉害呢?
  11. 在C++里while语句的一个妙用
  12. 编译Debian内核源码
  13. google翻译自动检测语言翻译成中文
  14. 牡丹-曹州牡丹:曹州牡丹
  15. 【Python】input()函数用法小结
  16. 封装win7系统,安装系统时提示:windows无法完成系统配置,若要尝试恢复配置,请重新启动计算机?
  17. 借助Writage,将 Word 转换为 Markdown发表csdn博客
  18. HyperLynx(二)LineSim的基本操作
  19. 前端实现打电话、发短信邮件
  20. c语言字符型常量计算,c语言字符型常量和变量.doc

热门文章

  1. 《结对-贪吃蛇-设计文档》
  2. redis 超时失效key 的监听触发
  3. 面向对象概述(课堂笔记)
  4. Django Python MySQL Linux 开发环境搭建
  5. ubuntu ssh 免密码登陆
  6. 4 int.parse方法调用问题和同行评审
  7. 在VB应用程序中调用Excel2000
  8. java8 stream to map_Java 8 Stream Api 中的 map和 flatMap 操作
  9. java 实现 常见排序算法(四)基数排序
  10. newcondition java_Java并发Condition接口