穷举/动态规划 求解商品最优价格问题

来源:互联网 发布:红蜻蜓软件下载 编辑:程序博客网 时间:2024/03/29 16:21

问题大意:商店进行优惠活动,每一件商品的价格达到500以上将对下一件商品减少200,达到1000减少500,达到2000减少1000.也可以将前几件商品看作一个组合(比如299,399,599),那么下一件商品就会减少500元,但是前三个商品不优惠.现在需要购买一系列商品,如何实现最优的购买策略?

此题穷举法可解:首先对所有商品进行排序,按照价格从高到低进行排序.然后寻找一个商品区间[0,k1],然后递归的求解区间[k1+1,n]的最优解.当然,需要注意的细节是在求解下一个区间是必须代入上一个区间的折扣.同时我们利用一个string变量记录相应的区间信息.

#include "iostream"#include "sstream"#include "vector"#include "cmath"#include "algorithm"#include "numeric"#define disc(price)     ((price < 500) ? 0:(price < 1000 ? 200:(price<2000?500:1000)))using namespace std;const long long int Inf = 2 << 29;long long int BestPrice = Inf;string route, bestroute;inline string tostring(int x){    stringstream sstream; sstream << x;    string res;    sstream >> res;    return res;}void Min_price(vector<int>::iterator left,vector<int>::iterator right,int discount,int all_price){    if (right - left == 1)//有一个商品    {           if (all_price + (((*left - discount) > 0) ? (*left - discount) : 0) < BestPrice)        {            bestroute = route + tostring(*(right-1));            BestPrice = all_price + (((*left - discount) > 0) ? (*left - discount) : 0);        }    }/*****************至少有两个商品***************/    auto iter = left;    int price = (*left - discount) > 0 ? (*left - discount) : 0;//获取上一个商品的折扣后的价格    auto temp = route;    while (++iter != right)    {        route += "[" + tostring(*left) + "," + tostring(*(iter - 1)) + "] " +            "discount : (" + tostring(disc(accumulate(left,iter,0))) + ") ->";//记录当前路径        Min_price(iter, right, disc(accumulate(left, iter, 0)), all_price + price);        route = temp;        price += *iter;//当前阶段累积商品总价格    }}int main(){    string s;    vector<int> data = {599,299,399,1000,1299,1298,990,988,2988};    sort(data.rbegin(), data.rend());    Min_price(data.begin(), data.end(), 0,0);    auto ans = dynamic_search(data);    cout << bestroute;    return 0;}

这里写图片描述
/******************************************************/

动态规划求解: F[i] = min{sum(i,k)+F[k+1]}

int dynamic_search(const vector<int>& data){    int length = data.size();    vector<int> F(length,Inf);    F[length - 1] = data[length - 1];    for (size_t i = length - 1; i != -1; --i)//求F[i]    {        for (size_t j = i; j != length-1; ++j)//F[i] = min{sum(i,k)+F[k+1]}        {            auto temp_sum = accumulate(data.begin() + i, data.begin() + j + 1, 0);            auto sum = temp_sum + F[j + 1] - min(disc(temp_sum), data[j + 1]);//减去相应优惠            if (F[i] > sum)                F[i] = sum;        }    }    return F[0];}
0 0
原创粉丝点击