饮料供货@编程之美

题目: 求出保证最大满意度的购买量?(供货总量是确定的)
假设共提供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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值