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