饮料供货@编程之美

题目:求出保证最大满意度的购买量?(供货总量是确定的)
假设共提供n中饮料,用(Si,Vi,Ci,Hi,Bi)(对应的饮料的名字,容量,可能的最大数量,满意度,实际购买量)
可能的购买量是指存货的上限。
饮料总容量为:求和i从0–n-1(Vi*Bi)

总满意度为:求和i从0–n-1(Hi*Bi)

通过对题目的分析,可以采用的算法包括动态规划、搜索以及贪心算法。
1.动态规划

首先选择动态规划,动态规划的话,状态转移函数为:

f[i][v] = max(f[i-1][v-k*c[i]]) + k*w[i]; 0 <= k <= n[i]

其中,c[i]表示选择i的cost,n[i]表示i能够选择的数量,w[i]表示选择i所带来的收益。

算法的具体实现如下:

    #include <iostream>
    #include <vector>
    using namespace std;
    /*
    *vv每种饮料的容量
    *cc每种饮料最大的数量
    *hh每种饮料的满意度
    *T饮料种类
    *V购买饮料的数量和
    */
    int dynamic(int vv[],int cc[],int hh[],int T,int V);
     
    int main ()
    {
        int vv[]={1,2,8,4,16};
        int cc[] = {50,20,30,50,20};
        int hh[]={3,4,2,5,2};
        int T = 5;
        int V = 100;
        cout << dynamic(vv,cc,hh,T,V);
    }
     
    int dynamic(int vv[],int cc[],int hh[],int T,int V)
    {
        const int INF = 1<<32-1;
        vector<vector<int> > dp(vector<vector<int> >(T+1,vector<int>(V+1,INF)));
        dp[T][0] = 0;//初始条件,表示当容量为0的时候,能够带来的收益是0
        for(int i = T-1;i >=0 ;i --)
        {
            for(int j = 0;j <= V;j ++)
            {
                for(int k = 0;k <= cc[i];k ++)
                {
                    if(j < k*vv[i]) break;
                    int x = dp[i+1][j-k*vv[i]];
                    if(x != INF)
                    {
                        x += k*hh[i];
                        if(x > dp[i][j])
                        {
                            dp[i][j] = x;
                        }
                    }
                }
            }
        }
        return dp[0][V];
    }


2 搜索

搜索的话,如果直接搜索,会产生很多不必要的计算过程,为了避免进行重复计算,采用备忘录,也就是一个表格,来保存计算的临时结果。

主要的思路为,如果要求d[0][v],那么就应该先求d[1][v-k*c[0]]的值,依次往后推,通过保留中间的计算过程,能够得到有效地值。

具体代码如下:

    #include <iostream>
    #include <vector>
    using namespace std;
    /*
    *vv每种饮料的容量
    *cc每种饮料最大的数量
    *hh每种饮料的满意度
    *T饮料种类
    *V购买饮料的数量和
    */
    const int INF= 1<<32 -1;
    int mysearch(int vv[],int cc[],int hh[],int curt,int curv,int T,int V,vector<vector<int> > &vvc);
    int main ()
    {
        int vv[]={1,2,8,4,16};
        int cc[] = {50,20,30,50,20};
        int hh[]={3,4,2,5,2};
        int T = 5;
        int V = 100;
        vector<vector<int>> vvc(T+1,vector<int>(V+1,-1));
        cout << mysearch(vv,cc,hh,0,V,T,V,vvc);
    }
     
    int mysearch(int vv[],int cc[],int hh[],int curt,int curv,int T,int V,vector<vector<int> > &vvc)
    {
        if(curt == T)
        {
            if(curv == 0)
            {
                return 0;
            }
            else
            {
                return INF;
            }
        }
        if(curv < 0)
        {
            return INF;
        }
        else if(curv == 0)
        {
            return 0;
        }
        else if(vvc[curt][curv] != -1) return vvc[curt][curv];
     
        int ret = -1;
        for (int i = 0;i <= cc[curt];i ++)
        {
            int tmp = mysearch(vv,cc,hh,curt+1,curv-i*vv[curt],T,V,vvc);
            if(tmp != INF)
            {
                tmp += i*hh[curt];
                if(tmp > ret)
                {
                    ret = tmp;
                }
            }
        }
        return vvc[curt][curv] = ret;
    }


3.贪心算法

书上有提到贪心算法,但是感觉贪心算法比较复杂,这里就不写出来了。可以参考:

http://blog.csdn.net/lichaoyin/article/details/9983883

http://blog.csdn.net/woniu317/article/details/20209055#t4
---------------------
作者:飞鸟Mu
来源:CSDN
原文:https://blog.csdn.net/flymu0808/article/details/38461015
版权声明:本文为博主原创文章,转载请附上博文链接!

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