前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >贪心算法求解:王者荣耀购买点券最优策略

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

作者头像
用户7656790
发布2020-09-21 14:48:34
9240
发布2020-09-21 14:48:34
举报

作者:古阙月

前言

放了大半年假的我如今开学了,说实话在屋里呆久了还不太愿意来学校。待了两天了,还是觉得屋里安逸,舍不得离开。不过来了学校自己不会像在家里那么懒惰了,每天打卡鞭策自己努力前行,早日达到毕业条件。

言归正传

下面开始描述问题:

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

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

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

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

贪心算法

这个时候,可能大都会想到两种算法:动态规划算法和贪心算法

这里容我偷个懒,采用简单易行的贪心算法。至于动态规划算法的解法感兴趣的小伙伴们可以自己试试看。至于贪心算法的核心理念:

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

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

代码语言:javascript
复制
package 贪心;
/*
作者     :XiangLin
创建时间 :2020/9/9 18:47
文件     :SkinBuy.java
IDE      :IntelliJ IDEA
*/

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 = getHowMoney(money);

        // 输出购买策略
        prin(buy,money);
    }

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

    /**
     * 根据贪心算法求出购买点券的策略
     * @param money    实际需要购买的点券数量
     * @return
     */

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

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

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

        return buy;
    }

    /**
     * 找到可以购买的点券数组中数额最大的但是不超过money点券数
     * @param money 实际需要购买的点券数量
     * @return
     */
    private static int maxCoupon(int money) {

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

    /**
     * 初始化变量,通过减去余额优惠卷等计算出实际需要购买的点券数量
     * @return
     */
    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;
    }

}

控制台输出结果得:

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

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

所有巧合的是要么是上天注定要么是一个人偷偷的在努力。

结束!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 五角钱的程序员 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 言归正传
  • 贪心算法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档