日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动态规划应用--双11购物凑单

發布時間:2024/7/5 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态规划应用--双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购物凑单的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。