《编程之美》读书随笔之六:饮料供货

题目在微软亚洲研究院上班,大家早上来的第一件事是干啥呢?查看邮件?No,是去水房拿饮料:酸奶,豆浆,绿茶、王老吉、咖啡、可口可乐……(当然,还是有很多同事把拿饮料当做第二件事)。

管理水房的阿姨们每天都会准备很多的饮料给大家,为了提高服务质量,她们会统计大家对每种饮料的满意度。一段时间后,阿姨们已经有了大批的数据。某天早上,当实习生小飞第一个冲进水房并一次拿了五瓶酸奶、四瓶王老吉、三瓶鲜橙多时,阿姨们逮住了他,要他帮忙。

从阿姨们统计的数据中,小飞可以知道大家对每一种饮料的满意度。阿姨们还告诉小飞,STC(Smart Tea Corp.)负责给研究院供应饮料,每天总量为V。STC很神奇,他们提供的每种饮料之单个容量都是2的方幂,比如王老吉,都是23=8升的,可乐都是25=32升的。当然STC的存货也是有限的,这会是每种饮料购买量的上限。统计数据中用饮料名字、容量、数量、满意度描述每一种饮料。

那么,小飞如何完成这个任务,求出保证最大满意度的购买量呢?

分析:具体见《编程之美》,下面的程序也是根据书上的几个解法来实现的:

#include<cstdlib>
#include<string>
#include<iostream>
using namespace std;
#define V 64
#define N 7

int opt[V+1][N+1];
int v[N]={2,4,8,2,4,8,16};
int c[N]={3,2,1,3,2,4,1};
int h[N]={20,30,25,30,15,30,100};

int cal(int y,int i)
{
  if(i==N)
  {
    if(V==0)
return 0;
else
return -10000;
  }
  if(V<0)
 return -10000;
  else if(V==0)
 return 0;
  else if(opt[V][i]!=-1)
 return opt[V][i];
  int ret=-1;
  for(int t=0;t<=c[t];t++)
  {
    int temp=cal(V-t*v[t],t+1);
if(temp!=-10000)
{
 temp+=h[t]*t;
 if(temp>ret)
 ret=temp;
}
  }
  opt[V][i]=ret;
  return opt[V][i];
}

//备忘录法
void memo_fun()
{
  for(int i=0;i<=V;i++)
  {
 for(int j=0;j<N;j++)
 {
 opt[i][j]=-1;
 }
  }
  int cc=cal(V,1);
  cout<<"biggest happiness is "<<cc<<endl;
}

//动态规划法
void dynamic_fun()
{
  opt[0][N]=0;
  for(int q=0;q<=N;q++)
 opt[0][q]=0;
  for(int i=1;i<=V;i++)
 opt[i][N]=-10000;
  for(int j=N;j>=0;j--)
  {
    for(int i=1;i<=V;i++)
{
 opt[i][j]=-10000;
 for(int k=0;k<c[j];k++)
 {
   if(i<k*v[j])
{
 break;
}
int x=opt[i-k*v[j]][j+1];
if(x!=-10000)
{
 x+=h[j]*k;
 if(x>opt[i][j])
 {
   opt[i][j]=x;
 }
}
 }
}
  }
  cout<<"the biggest happiness is: "<<opt[V][0]<<endl;
}

int main()
{
   cout<<"动态规划算法实现"<<endl;  
   dynamic_fun();  
   cout<<"备忘录算法实现"<<endl;  
   memo_fun();  
   system("pause");  
   return 0;  
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值