编程之美饮料供货:动态规划解法

编程之美--饮料供货

共有n种饮料,每种饮料都有自己的名字、1瓶这种饮料对应的容量(单位:L)、可供应这种饮料的最大数量、以及1瓶此种饮料的满意度、实际购买这种饮料的瓶数。

我们定义一个表示饮料的结构体。分别用name、capacity、maxNumber、happiness、purchaseNumber对应以上属性。

问题要求:给定可提供饮料的最大供应量totalSupport(单位为L),要求饮料购买方案,使得购买方案对应的满意度最大。

解决方法:

应用动态规划求解,

假设用satisfy[n][L]表示在最大供应量为L的情况下,选择前n种饮料是的购买方案对应的最大满意度。则

satisfy[i][j] 就表示在最大供应量为j的情况下,选择前i中饮料的购买方案对应的最大满意度,并且有:

如果 j < capacity;satisfy[i][j] = satisfy[i - 1][j]

如果 j > capacity;satisfy[i][j] = max{satisfy[i - 1][j - k * capacity] + k * happiness, k = 0, 1, 2, 3, ..., maxNumber,并且k要使得 j-k * capacity >= 0}。这个式子最直观的解释就是,提供最大供应量j,在前i种饮料中选择。并且最大供应量j大于单位体积的第j种饮料。那么对于第j种饮料,我可以分别考虑买0、1、2、...瓶第j种饮料的情况。然后选择一个使满意度最大的购买方案。

上面就是动态规划方法递推公式。用上面的公式,就可以建立表格了!



    #include <iostream>
    #include <vector>
    #include <string>
    using namespace std;
     
    struct Goods{
        string name;//饮料的名字名字
        int capacity;//单位饮料的容量,单位:L
        int maxNumber;//可供应饮料的最大数量,单位:个
        int happiness;//对单位饮料的满意度
        int purchaseNumber;//对饮料的实际购买数量,单位:个
        Goods() : name(20, '0'), capacity(0), maxNumber(0), happiness(0), purchaseNumber(0){
        }
    };
     
    //输入饮料信息
    void getGoodsInformation(vector<Goods> &goods){
        size_t n = goods.size();
        if (n == 0){
            return;
        }
        cout << "请依次输入饮料的名称、单位饮料的容量、可供应此种饮料的最大数量、对此种饮料的满意度:";
        for(size_t i = 0; i != n; i++){
            cin >> goods[i].name >> goods[i].capacity >> goods[i].maxNumber >> goods[i].happiness;
        }
        return;
    }
    //输出达到最大满意度的饮料购买方案
    void getAndPrintBuy(vector<Goods> &goods, vector<vector<int> > &state, vector<int> &buy, int totalSupport){
        int theNumberofGoods = buy.size();
        for(int i = theNumberofGoods - 1; i >= 0; i--){
            if (totalSupport == 0){
                break;
            }
            int k = state[i+1][totalSupport];
            buy[i] = k;
            totalSupport -= (k * goods[i+1-1].capacity);
        }
        cout << endl << "饮料购买方案为:" << endl;
        for(int i = 0; i < theNumberofGoods; i++){
            cout << "饮料名:" << goods[i].name << " 购买数量:"<< buy[i] << endl;
        }
    }
    //使用动态规划求解
    int getMaxSatisfy(vector<Goods> &goods, int totalSupport){
        //定义二维数组satisfy
        int theNumberofGoods = goods.size();//饮料的种类
        vector<vector<int> > satisfy(theNumberofGoods + 1, vector<int> (theNumberofGoods + 1, 0));
        vector<vector<int> > state(theNumberofGoods + 1, vector<int> (theNumberofGoods + 1, -1));
     
        //初始化边界条件
        for(int i = 0; i <= theNumberofGoods; i++){
            satisfy[i][0] = 0;
        }
        for(int j = 0; j <= totalSupport; j++){
            satisfy[0][j] = 0;
        }
     
        for(int i = 1; i <= theNumberofGoods; i++){
            for(int j = 1; j <= totalSupport; j++){
                int maxHappiness = 0;
                int purchaseNumber = 0;
                for(int k = 0; k <= goods[i - 1].maxNumber; k++){
                    if(goods[i-1].capacity * k > j){
                        break;
                    }
                    int temp = 0;
                    temp = satisfy[i - 1][j - k * goods[i-1].capacity] + k * goods[i-1].happiness;
                    if (temp > maxHappiness){
                        maxHappiness = temp;
                        purchaseNumber = k;
                    }
                }
                satisfy[i][j] = maxHappiness;
                state[i][j] = purchaseNumber;
            }
        }
        //输出satisfy矩阵
        for(int i = 0; i <= theNumberofGoods; i++){
            for(int j = 0; j <= totalSupport; j++){
                cout << satisfy[i][j] << " ";
            }
            cout << endl;
        }
        vector<int> buy(theNumberofGoods, 0);
        getAndPrintBuy(goods, state, buy, totalSupport);
        return satisfy[theNumberofGoods][totalSupport];
    }
     
    int main(void){
        int n;
        cout << "输入商品的种类n" << endl;
        cin >> n;
        vector<Goods> vec(n);
        getGoodsInformation(vec);
        int max = 0;
        int totalSupport;//总的饮料提供量, 单位:L
        cout << "输入总的饮料提供量,单位为L:" << endl;
        cin >> totalSupport;
        max = getMaxSatisfy(vec, totalSupport);
        cout << "最大满意度为:" << max << endl;
        return 0;
    }
---------------------
作者:wly_2014
来源:CSDN
原文:https://blog.csdn.net/wly_2014/article/details/51438232
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-07-19 12:26  天涯海角路  阅读(224)  评论(0)    收藏  举报