記一次優惠券最優使用算法

記一次優惠券最優使用算法

先說一下業務背景。公司做的一個投資的APP,投資金額可以用優惠券抵扣。紅包面額(100,50,30,10)

優惠券使用規則:

  • 優先使用大面額的紅包,即優先使用張數最少的紅包組合
  • 優先使用有限制的紅包,即優先使用有限制紅包張數占比最大的組合
  • 優先使用即將過期的紅包,即優先使用平均有效期最短的組合
  • 選擇紅包面額之和最大的組合(面額總值≤投資額*1%)

算法嘗試

前面三個都可以通過數據庫檢索排序實現生成一個數組,最后一個就要使用程序算法實現了。
一開始有想過背包法、窮舉法。

  • 背包法:說實在的,沒看懂(比較尷尬),實現是可以實現。但是無法獲取具體使用了哪張優惠券(簡單就是很難獲得優惠券的Id)
  • 窮舉法:數據太多,不可控。

優惠券最優算法1.0

算出用戶本次投資最大使用優惠券總額(redAmount)、獲取用戶的優惠券列表(redCoupons)(已按前三規則排序)直接上代碼:

    public function dealCoupon()
    {
        $redCoupons =[]; $restRedAmount = 100;

        $redCouponIdLists = []; $restRedAmounts = [];
        $arrCount = count($redCoupons);
        for ($i=0; $i<$arrCount; $i++) {
            list($redCouponIdList, $restRedAmount) = getBestCoupon($redCoupons, $restRedAmount);
            if ($restRedAmount == 0) {
                $bestCouponIdList = $redCouponIdList;
                break;
            }

            $redCouponIdLists[] = $redCouponIdList;
            $restRedAmounts[] = $restRedAmount;
            array_shift($redCoupons);
        }

        if (empty($bestCouponIdList)) {
            $pos = array_search(min($restRedAmounts), $restRedAmounts);
            $bestCouponIdList = $redCouponIdLists[$pos];
        }

    }

    /**
     * 紅包最優算法
     */
    private function getBestCoupon($redCoupons, $restRedAmount)
    {
        $redCouponAmount = 0;
        foreach ($redCoupons as $redCoupon) {
            if ($restRedAmount >= $redCoupon->getAmount()) {
                $redCouponAmount   = $redCouponAmount + $redCoupon->getAmount());
                $redCouponIdList[] = $redCoupon->getCouponId();
                $restRedAmount     = $restRedAmount - $redCoupon->getAmount();

                if ($restRedAmount == 0) break;
            }
        }

        return [$redCouponIdList, $restRedAmount];
    }

實例解析:用戶投資9000,用戶有優惠券(50,30,30,30,30)

  • 用50塊嘗試,最多80
  • 用第一個30嘗試,最多90,已經最優,中斷程序(否則繼續向下類推)

問題

  • 因為每次算完就把該紅包從數組中推出,這樣還是存在問題。例如投資1600,用戶有(100,50,30,30)。這樣就不會出現最優。

解決(算法2.0)

  • 不把計算過優惠券推出,需要每次把要計算那張優惠券單獨拿出來
  • 這樣程序復雜了很多,但還是可以實現的
  • 這樣還是會出現算法1.0的問題,不過這種按照順序取優惠券很難不出現問題。但是這種面額的優惠券出現幾率幾乎沒有

請教

  • 期待有大神給出更好的算法
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 你看,海的那一邊 星辰匯集著 浪花在耳邊拍打著 我們出發吧 我眼中的光呢 為何它時隱時現 在我最為潦倒之時 突然讓...
    學忽局長閱讀 205評論 0 1
  • 長假即將結束,帶寶貝去了野生動物園。 辦了年卡 看來以后要常來打卡了。 ORT: 3本 RAZ: our camp...
    佳茗媽閱讀 121評論 0 0
  • 想說點什么,千言萬語卻開不了口,想寫點什么,千絲萬縷卻沒有頭緒,喜歡你的瀟灑,卻痛恨你的放肆,回憶你的好,卻也記起...
    冰糖檸檬閱讀 221評論 0 2