貪心算法求解:王者榮耀購買點券最優策略

哪裏會有人喜歡孤獨,只不過是不喜歡失望。

有目錄,不迷路

前言

最近看了下《算法圖解》確實給本身很多啓發,感受本身看世界都多了一個角度、多了一分透徹,就連玩遊戲的時候也是如此。不過書中的代碼示例都是用python來實現的,而本人是以java爲主攻方向。因此,就閱讀體驗上來說,未免讓我有些不快。爲此,我特地將書中的python代碼都一一翻譯成了Java代碼。連接以下:java

肝了幾萬字,送給看了《算法圖解》倒是主攻Java的你和我(上篇)


肝了幾萬字,送給看了《算法圖解》倒是主攻Java的你和我(下篇)
python

言歸正傳

下面開始描述問題:算法

本人平時比較喜歡玩王者榮耀,最近玩韓信比較多,就想買一個韓信街頭霸王的皮膚。數組

在這裏插入圖片描述

可是在購買點券的過程當中發現這樣一個問題url

在這裏插入圖片描述
我居然不可以爲所欲爲的購買點券數量,只能按照騰訊規定的數量購買點券。這應該是騰訊爲了刺激用戶消費所設置的規則。畢竟本身去湊點券數量也不太好計算,嫌麻煩的用戶可能就會直接購買超量的點券。可是這個時候我忽然就想挑戰一波,拒絕超量消費(實際上是窮 )。因而闡述問題試圖求解:
spa

若是我想買一個韓信街頭霸王的皮膚,已知皮膚的價格爲888點券,而我有50點券的優惠卷,餘額爲8點券,也就是說我需 要購買830點券。可是購買點券的數量又不能爲所欲爲,如上圖所示。可是由於最小單位是1元,也就是10點券,因此我確定能夠湊的剛恰好。問:如何花最少的次數恰好買到830點券?.net

貪心算法

這個時候,可能大都會想到兩種算法:動態規劃算法和貪心算法
這裏容我偷個懶,採用簡單易行的貪心算法。至於動態規劃算法的解法感興趣的小夥伴們能夠本身試試看。至於貪心算法的核心理念,以前的博客也提到過:
翻譯

每一步都採起最優的作法。用專業術語來說就是:每一步都選擇局部最優解,進而但願最終得到一個全局最優解。3d

代碼以下,註釋仍是蠻詳細的:code

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

/** * @author guqueyue * @Date 2020/8/24 * 韓信買皮膚問題 **/
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);

    }

    /** * 在控制檯打印出購買策略 * @param buy 購買集合 * @param 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 + " ");
        });
    }

    /** * 初始化變量,經過減去餘額優惠卷等計算出實際須要購買的點券數量 * @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;
    }

    /** * 根據貪心算法求出購買點券的策略 * @param money 實際須要購買的點券數量 * @return */
    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;
    }

    /** * 找到能夠購買的點券數組中數額最大的可是不超過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;
    }
}

控制檯輸出結果得:
在這裏插入圖片描述
哼哼,完美!通過這麼一番折騰,買皮膚都變得問心無愧了:
在這裏插入圖片描述
升到了貴族6, 還送了一個狄仁傑的皮膚:
在這裏插入圖片描述

相關文章
相關標籤/搜索