动态规划应用--双11购物凑单
生活随笔
收集整理的這篇文章主要介紹了
动态规划应用--双11购物凑单
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 1. 問題描述
- 2. 代碼實現
1. 問題描述
雙11購物節的時候,某寶給你很多張滿300減50的優惠券,你想組合各種商品的價格總和>=300,且金額總和越接近300越好,這樣可以多薅點羊毛。
- 回溯算法效率太低,時間復雜度指數級。當n很大的時候,可能“雙11”已經結束了,代碼還沒有運行出結果
- DP求解:購物車中有n個商品。針對每個商品都決策是否購買。每次決策之后,對應不同的狀態集合。
- 用一個二維數組 states[n][x],來記錄每次決策之后所有可達的狀態。不過,這里的x值是多少呢?
- 0-1背包問題中,我們找的是小于等于MaxWeight的最大值,x 就是背包的最大承載重量 MaxWeight+1。
- 對于這個問題來說,我們要找的是>=300(滿減條件)的值中最小的,所以就不能設置為300加1了。就這個實際的問題而言,如果要購買的物品的總價格超過300太多,比如1000,那這個羊毛“薅”得就沒有太大意義了。所以,我們可以限定x值為1001。
- 這個問題不僅要求>=300的總價格中的最小的,還要找出這個最小總價格對應都要購買哪些商品。實際上,我們可以利用states數組,倒推出這個被選擇的商品序列。
2. 代碼實現
/*** @description: 雙十一購物湊單(DP)* @author: michael ming* @date: 2019/7/17 0:29* @modified by: */ #include <cstring> #include <iostream>const int limitMoney = 300; const int MaxSumOfPrice = 3*limitMoney;//超過3倍就沒有媷羊毛的必要了 void double11shopping(int *price, int n) {bool (*states) [MaxSumOfPrice+1] = new bool [n][MaxSumOfPrice+1];memset(states,0,n*(MaxSumOfPrice+1)*sizeof(bool));states[0][0] = true;//第一個不買if(price[0] <= MaxSumOfPrice)states[0][price[0]] = true;//第一個買int i, j;for(i = 1; i < n; ++i)//動態規劃{for(j = 0; j <= MaxSumOfPrice; ++j)//不買第i個商品{if(states[i-1][j] == true)states[i][j] = states[i-1][j];}for(j = 0; j <= MaxSumOfPrice-price[i]; ++j)//購買第i個商品{if(states[i-1][j] == true)states[i][j+price[i]] = true;}}for(j = limitMoney; j <= MaxSumOfPrice; ++j){if(states[n-1][j] == true)break;//找到>=滿減金額的最小值}if(j == MaxSumOfPrice+1)return;//超出滿減金額很多,沒必要選了,直接買吧for(i = n-1; i >= 1; --i)//打印該買的商品{if(j-price[i] >= 0 && states[i-1][j-price[i]] == true){std::cout << "購買價格為:" << price[i] << " 的商品" << std::endl;j = j - price[i];}//else 沒有購買這個商品,j不變}if(j != 0)//如果沒有買第0個,到這里j == 0了,如果j不為0,說明買了第0個std::cout << "購買價格為:" << price[0] << " 的商品" << std::endl;delete [] states; } int main() {const int n = 5;int price[n] = {100,98,105,104,99};double11shopping(price,n);return 0; }打印所選商品說明:
- 狀態(i,j)只有可能從(i-1,j)或者(i-1,j-price[i])兩個狀態推導過來。所以,我們就檢查這兩個狀態是否可達,也就是 states[ i-1 ][ j ] 或者 states[ i-1 ][ j-price[i] ] 是否是true。
- 如果states[ i-1 ][ j ]可達,說明沒有選擇第i個商品,如果states[ i-1 ][ j-price[i] ] 可達,說明選擇了第i個商品。從中選擇一個可達的狀態(如果兩個都可達,就隨意選擇一個),然后,繼續迭代考察其他商品是否有選擇購買。
總結
以上是生活随笔為你收集整理的动态规划应用--双11购物凑单的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LeetCode 938. 二叉搜索树的
- 下一篇: LeetCode 657. 机器人能否返