贪心算法求解:王者荣耀购买点券最优策略

   日期:2020-09-06     浏览:95    评论:0    
核心提示:最近看了下《算法图解》确实给自己不少启发,感觉自己看世界多了一个角度、多了一分透彻,就连玩游戏比如王者荣耀的时候也是如此..
哪里会有人喜欢孤独,只不过是不喜欢失望。

有目录,不迷路

  • 前言
  • 言归正传
    • 贪心算法

前言

最近看了下《算法图解》确实给自己不少启发,感觉自己看世界都多了一个角度、多了一分透彻,就连玩游戏的时候也是如此。不过书中的代码示例都是用python来实现的,而本人是以java为主攻方向。所以,就阅读体验上来讲,未免让我有些不快。为此,我特意将书中的python代码都一一翻译成了Java代码。链接如下:

肝了几万字,送给看了《算法图解》却是主攻Java的你和我(上篇)

肝了几万字,送给看了《算法图解》却是主攻Java的你和我(下篇)

言归正传

下面开始描述问题:

本人平时比较喜欢玩王者荣耀,最近玩韩信比较多,就想买一个韩信街头霸王的皮肤。

但是在购买点券的过程中发现这样一个问题


我竟然不能够随心所欲的购买点券数量,只能按照腾讯规定的数量购买点券。这应该是腾讯为了刺激用户消费所设置的规则。毕竟自己去凑点券数量也不太好计算,嫌麻烦的用户可能就会直接购买超量的点券。但是这个时候我突然就想挑战一波,拒绝超量消费(其实是穷 )。于是阐述问题试图求解:

如果我想买一个韩信街头霸王的皮肤,已知皮肤的价格为888点券,而我有50点券的优惠卷,余额为8点券,也就是说我需 要购买830点券。但是购买点券的数量又不能随心所欲,如上图所示。但是因为最小单位是1元,也就是10点券,所以我肯定可以凑的刚刚好。问:如何花最少的次数刚好买到830点券?

贪心算法

这个时候,可能大都会想到两种算法:动态规划算法和贪心算法
这里容我偷个懒,采用简单易行的贪心算法。至于动态规划算法的解法感兴趣的小伙伴们可以自己试试看。至于贪心算法的核心理念,之前的博客也提到过:

每一步都采取最优的做法。用专业术语来讲就是:每一步都选择局部最优解,进而希望最终获得一个全局最优解。

代码如下,注释还是蛮详细的:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;


public class SkinBuy {

    // 可以购买的点券数量
    static int[] coupon = {10, 60, 180, 300, 680, 1180, 1980};

    public static void main(String[] args) {

        // 初始化变量,通过减去余额优惠卷等计算出实际需要购买的点券数量
        int money = getMoney();

        // 根据贪心算法得到如何购买的点券集合
        List<Integer> buy = getHowBuy(money);
        // 输出购买策略
        print(buy, money);

    }

    
    private static void print(List<Integer> buy, int money) {
        System.out.println("尊敬的腾讯抠门用户,您最少需要花 " + buy.size() + " 次才能刚好凑到" + money + "点券");
        System.out.print("您只需要这样购买点券:");
        buy.forEach(b -> { // 遍历点券集合输出即可
            System.out.print(b + " ");
        });
    }

    
    private static int getMoney() {

        Scanner input = new Scanner(System.in);

        // 皮肤的价钱 - 888点券
        System.out.print("请输入您要购买皮肤的价格(点券):");
        int price = input.nextInt();

        // 账户余额 - 8点券
        System.out.print("请输入您的账户余额:");
        int banlance = input.nextInt();

        // 优惠卷 - 50点券
        System.out.print("请输入您的优惠卷:");
        int discount = input.nextInt();

        // 实际需要购买的点券
        int money = price - banlance - discount;

        return money;
    }

    
    private static List<Integer> getHowBuy(int money) {

        List<Integer> buy = new ArrayList<>();

        while (money > 0) {
            // 找到可以购买的点券数组中数额最大的但是不超过money点券数
            int maxCoupon = maxCoupon(money);
            money -= maxCoupon;
            buy.add(maxCoupon);
        }

        return buy;
    }

    
    private static int maxCoupon(int money) {

        // 默认为10 - 最小点券购买数
        int maxCoupon = 10;
        for (int m : coupon) {
            // 有序数组才可以这样
            if (money > m){
                maxCoupon = m;
            }
        }

        return maxCoupon;
    }
}

控制台输出结果得:

哼哼,完美!经过这么一番折腾,买皮肤都变得心安理得了:

升到了贵族6, 还送了一个狄仁杰的皮肤:

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服