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

问题大意:商店进行优惠活动,每一件商品的价格达到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;
}

穷举/动态规划 求解商品最优价格问题_第1张图片
/******************************************************/

动态规划求解: 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];
}

你可能感兴趣的:(穷举/动态规划 求解商品最优价格问题)