作者 |  小鹿

来源 |  一个不甘平凡的码农

都说程序员是直男,聊天聊不过三句,看下边这位朋友求助小鹿,抱怨说,学习数据结构那么难,除了优化程序算法,其他的啥都不能干,学它干啥,哎,撩个妹子都撩不到。

说真的,我都嫌弃他,哈哈,嫌弃归嫌弃,我还想教给你撩妹的正确方式的,该说不说的,为了能让这位朋友可以撩上妹子,小鹿耗时假期三天时光,出了这篇文章,希望帮助各位宅男们脱单。

故事情节正在生成中......

故事背景

快过年了,很多吃货都安奈不住了,也包括爱吃零食的小鹿。天猫超市也很多“满减活动”。我想很多程序员和小鹿一样,会在天猫超市有“满减活动”的时候才会买一大些零食,一次性吃个够。

那么机会来了,你是个吃货,很多小姐姐也是吃货,何不借此机撩一撩呢

这怎么撩?凭着你学了数据结构与算法嘛?凭着你是做底层架构的?凭着你会....

这点小事,包在小鹿身上了,下面就给你来个用数据结构与算法实战撩小姐姐,让小姐姐对你的满意度从 0 飙升到 100。

 开始搭讪

很多女生说程序员都是直男,没错,我也承认我也是其中一位。

直男是程序员的通病,但是程序员这个职业也赋予了我们随机应变能力呀,懂得自救才行(很多宅男们就败在这了)。

你不仔细想想,作为一个非程序员的妹子,谁喜欢跟你闲着没事讨论这自己不懂的东西。

 帮小姐姐解决问题

这个时候,该你展现真正的技术了,可不要搞砸了,不认你的印象又被小姐姐大大降低。

那么问题来了,怎么选择购物车中的零食才能满足尽最大可能凑到“满减活动”呢?

1、动态规划

我们就会用到动态规划去计算,动态规划在数据结构与算法中属于重点也是难点,也会涉及到递归,这部分也是基础中最难的。之前很多读反馈,说分享的教程太基础,所以关于递归基础,这里不讲了,可以公众号后台回复“递归”,获取基础教程。

首先,我们将复杂问题简单化,假如我们购物车中有 2元、4元、2元、3元、6元的五个价格的零食。假如买够 9 元,我们立减 5 元,我们应该凑满 9 元或者尽可能的大于 9 元并接近 9 元呢?

其实这个问题一眼就能选择出来,但是我们为了将复杂问题解决掉,我们还是用动态规划去解决。

其实这个问题类似于递归,第一个零食买不买有两种选择,一个是买,一个就是不买,第二个、第三个、第四个..... 都有两种选择,这时候我们可以用到递归。

你会说,我们可以用回溯算法把所有可能列出来呀,选择合适的不就好了?记住,我们是程序员,要尽可能的降低时间复杂度,等你全部穷举出来,估计你的小姐姐早就等不及下单了。

这个问题用动态规划怎么解决呢?

我们用(a,b)来表示每个零食是否被选择,a 表示对第 a 个零食是否购买,b 表示已选择购买零食的总价格。

2、用递归树来表示

上边的递归树把所有的情况都列举了出来,就像是我们用到的回溯算法,之所以时间复杂度很高,是因为递归树中有的层次很多重复计算的步骤,如果我们把重复计算的状态只记录一种不就可以减少时间复杂度,提高程序效率了吗?

上边的递归树怎么表示呢?我们可以一个二维数组,tree[a][b],a 表示第 a 个零食是否购买,b 表示已选择购买零食的总价格。

上边递归树我们用代码实现,如下:

 1/** 2 *  3 * @param prices 各个商品的价格 4 * @param n 商品的个数 5 * @param w 满减条件(满 199-99元) 6 */ 7public static void ShoppingSnacks(int[] prices,int n,int w){ 8    boolean[][] tree = new boolean[n][w+1]; 9    tree[0][0] = true;10    tree[0][prices[0]] = true;11    //动态规划12    for (int i = 1; i < n; i++) {13        // 不购买当前商品14        for(int j = 0;j <=w; j++) {15            //寻找上一个商品决策状态16            if(tree[i-1][j] == true) {17                tree[i][j] = true;18            }19        }2021        // 购买当前商品22        for(int j = 0;j <=w-prices[i]; j++) {23            //寻找上一个商品决策状态24            if(tree[i-1][j] == true) {25                tree[i][j+prices[i]] = true;26            }27        }28     }29}30

上边代码执行完成,所有的情况我们就用二维数组来表示,零食购买的决策状态如下:

横坐标代表已经从购物车选择的零食的总价格;
纵坐标代表对第 i 个零食进行选择是否购买;

但是上边的代码存在一个问题,求得的最大满足满减条件价格是尽可能小于接近 9 元,我们想要达到的结果是尽可能的达到或超过接近满减条件。怎么做呢?

我们做出以下修改,让满减价格尽可能的大三倍,就是说我们将满足 9 元提升到 27 元,也就是说,在所有零食中,尽可能满足接近 27 元的情况有哪些,我们都能选择出来,接下来我们选择出最接近超过 9 元的情况就可以了。

代码修改如下:

 1/** 2 *  3 * @param prices 各个商品的价格 4 * @param n 商品的个数 5 * @param w 满减条件(满 199-99元) 6 */ 7public static void ShoppingSnacks(int[] prices,int n,int w){ 8    //将商品的价格扩展到三倍 9    boolean[][] tree = new boolean[n][3*w+1];10    tree[0][0] = true;11    tree[0][prices[0]] = true;12    //动态规划13    for (int i = 1; i < n; i++) {14        // 不购买当前商品15        for(int j = 0;j <=3*w; j++) {16            //寻找上一个商品决策状态17            if(tree[i-1][j] == true) {18                tree[i][j] = true;19            }20        }2122        // 购买当前商品23        for(int j = 0;j <=3*w-prices[i]; j++) {24            //寻找上一个商品决策状态25            if(tree[i-1][j] == true) {26                tree[i][j+prices[i]] = true;27            }28        }29     }30}31

那么还有一个问题就是最大可能超过并接近 9 元的情况我们选择出来了,但是怎么把选择的哪些零食列出来呢?

我们利用倒推的方法,这个地方很难理解,可以自己尝试着画图或者根据代码和上边画的二维数组图对应着选择,多看几遍估计就可以看会了,问题不大。

怎么个倒推法呢?假如我们最后一个商品在数组中用 n-1 表示,如果可以通过 tree[n-2][ j - prices[i]],或者 tree[i-1][j] 推到出来,那么这两种状态可以达到,就可以判断当前的这个零食是否购买,如果两种状态都可以达到,我们选择一种就好,以为有这样一种情况就是,到达满减最接近的值可能有很多中情况。

上边介绍完了,那么给小姐姐选择零食尽最大可能的接近满减(199元),我们就可以享受立减 99 元的优惠了!

购物车物品如下:

我们会发现一个问题,小数不能用下标表示,那我们可以将价格以及满减价格同时乘以10,那么就可以计算了。

代码如下:

 1/** 2 * 【动态规划】 3 * 功能:实现天猫超市 “满减凑单活动” 4 * @author 小鹿 5 * 6 */ 7public class TBShopping { 8 9    /**10     * 11     * @param prices 各个零食的价格12     * @param n 零食的个数13     * @param w 满减条件(满 199-99元)14     */15    public static void ShoppingSnacks(int[] prices,int n,int w){16        //将零食的价格扩展到三倍17        boolean[][] tree = new boolean[n][3*w+1];18        tree[0][0] = true;19        tree[0][prices[0]] = true;2021        //动态规划22        for (int i = 1; i < n; i++) {2324            // 不购买当前零食25            for(int j = 0;j <=3*w; j++) {26                //寻找上一个零食决策状态27                if(tree[i-1][j] == true) {28                    tree[i][j] = true;29                }30            }3132            // 购买当前零食33            for(int j = 0;j <=3*w-prices[i]; j++) {34                //寻找上一个商品决策状态35                if(tree[i-1][j] == true) {36                    tree[i][j+prices[i]] = true;37                }38            }39        }4041        //找出需要凑单的零食42        int j;43        for(j = w;j < 3*w+1; j++) {44            //在最后一个零食寻找满足最接近 200 的条件状态45            if(tree[n-1][j]==true) { 46                System.out.println("满减的最大条件为"+(float)j/10+"元");47                break;48            }49        }5051        //没有可选择零食52        if(j == -1) {53            return;54        }5556        // 倒推遍历满足条件的零食57        for(int i = n-1; i>=1; i--) {58            //当前账单的总金额大必须于当前零食金额59            //且上一个商品的决策状态为 true60            if(j - prices[i]>=0 && tree[i-1][j-prices[i]] == true) {61                //已购买该零食62                System.out.println(Snacks[i]+p[i]);63                j = j - prices[i];64            }else {65                //没有购买该零食6667            }68        }69        if(j != 0) {70            System.out.print(Snacks[1]+p[0]);71        }72    }73}

运行结果:

当你给小姐姐完成了这项艰巨的选择之后,小姐姐的态度就180 度大转弯了!

也许,你脱单的日子到了,脱单了别忘了回来小鹿点个好看转发朋友圈,让你身边更多的宅男们脱单。

【源码获取方式】:公众号回复“撩妹源码”,即可免费获取小鹿精心整理“满减凑单”的全部源码。

「一个不甘平凡的码农」一直专注于原创输出。

长按识别二维码关注

小鹿公众号专注于「前端」、「数据结构」互联网技术领域,通俗简单的文字和动漫配图,让你爱上编程。


?扫描上方二维码关注小詹

【实战篇】| 小鹿教你用动态规划撩妹的正确方式相关推荐

  1. 用动态规划撩妹的正确方式

    Linux编程 点击右侧关注,免费入门到精通! 作者 |  小鹿 来源 |  一个不甘平凡的码农 都说程序员是直男,聊天聊不过三句,看下边这位朋友求助小鹿,抱怨说,学习数据结构那么难,除了优化程序算法 ...

  2. 寂寞约会吧客服务器的微信是多少钱,约会专家倪淙岩:72招教你如何微信撩妹...

    10.24是一个特殊的日子-程序员关爱日,关爱他们得从你我做起,小编帮你帮到这里.程序员是一类十分需要我们关爱的群体,挖财和饿了么最近联合发布了<互联网从业者生活品质报告>,从报告数据显示 ...

  3. N个Linux耍酷命令,手把手教你如何技术撩妹!

    点击关注公众号,实用技术文章及时了解 来源:toutiao.com/a6820664143654158861 自打进入技术运维领域,相信很多小伙伴每日都是技术身傍(绑),Linux .docker.k ...

  4. python撩妹技能_干货必看 | 手把手教你用Python撩妹

    今天我们不讲专业知识,我们来讲讲,如何用Python做个撩妹小程序,考虑到有些小白没有深入的学习过Python,我给大家整理个初阶小白也可以做出来的程序,画颗爱心. 以下是代码: 1 from tur ...

  5. 几个 Linux 耍酷命令,手把手教你如何技术撩妹!技术脱单

    点击关注公众号,回复"1024"获取2TB学习资源! 一入运维深似海,从此女友是路人~自打进入技术运维领域,相信很多小伙伴每日都是技术身傍(绑),Linux .docker.k8s ...

  6. 女神节▍教你用Python撩妹:微信推送天气早报/睡前故事/精美图片

    女神节 首先,谨代表我自己以及剩下的1,2,3,4,5,6,7--个光棍程序员向今日所有过节的小姐姐们道一声"节日快乐,女王大人". 女神节,当然也要送小姐姐们礼物了,谁叫咱是程序 ...

  7. 你知道豆瓣电影是怎么评分的吗?(实战篇—手把手教你分析豆瓣电影)

    点赞再看,养成好习惯 Python版本3.8.0,开发工具:Pycharm 写在前面的话: 如果你是因为看到标题进来的,那恭喜你,又多了一个涨(入)知(坑)识的机会. 在这篇豆瓣电影Top250的分析 ...

  8. 实战篇:教你建设企业销售分析系统

    企业每天都在制造大量的经营数据,这些数据反映了企业生成.销售状况.营销分析是在广泛收集信息资料的基础上,运用各种定性和定量的方法,帮助管理层决策分析,更好的为开展营销工作服务. 一般而言营销管理分析系 ...

  9. 做实验、修电脑、命题相亲……Python大佬教你七夕如何撩妹

    在Google上输入Love,可以搜到12,220,000,000条结果. 关于爱情,中国古诗有"愿得一人心 白首不相离"这样的美句,西方有Love never fails的谚语. ...

最新文章

  1. EM算法(Expectation Maximization)期望最大化算法
  2. Java中多态(向上转型)机制
  3. Linux 操作系统太难?先爬过这 6 个陡坡
  4. 牛客练习赛69D-火柴排队【dp】
  5. 5分钟k线数据 存储_成功率极高的“分时K线战法”:15分钟K线战法+30分钟K线战法...
  6. 工业机器人专业展板图片_南充职业技术学院工业机器人专业线下课程开展情况...
  7. Boost笔记--Thread--Ubuntu上初次使用时遇到的问题
  8. Flex beta2+XFire开发实例
  9. 11-24 EDEM-FLUENT 耦合步骤
  10. 点云数据的类型主要分为_点云数据处理方法概述
  11. 计算机程序员crc算法,CRC-8校验原理及软件实现
  12. msxml6 C++
  13. 老婆生成器 yyds
  14. 抗击疫情 融云在行动
  15. 齐齐哈尔大学考研计算机专业,齐齐哈尔大学(专业学位)计算机技术研究生考试科目和考研参考书目...
  16. python输入一个浮点数、输出其整数部分和小数部分_输入一个浮点数,并输出该数的整数部分和小数部分...
  17. 福建农林大学计算机分数线,福建农林大学录取分数线2021是多少分(附历年录取分数线)...
  18. 多账户交易PAMM / MAM
  19. 企业微信外部群和内部群有什么区别?如何创建外部群
  20. 人生无常,该来的总会来

热门文章

  1. Window下PHP 安装redis扩展
  2. PHP内核探索:新垃圾回收机制说明
  3. Fiddler 从安装到使用 (creation of the root certificate wasn)
  4. MySQL中merge表存储引擎用法
  5. PHP算法按数组某一字段进行排序
  6. aspx repeater 用法_ASP.NET - Repeater 控件
  7. 计算机软件员证书用途,软考证书的五大好处(详解)
  8. HTTP使用BASIC认证的原理及实现方法
  9. php fpm 不写errorlog,PHP-FPM不写入错误日志
  10. python文件输出中文_【python】中文的输出,打印,文件编码问题解决方法