编程之美——饮料供货
来源:互联网 发布:澳洲国立大学人工智能 编辑:程序博客网 时间:2024/04/29 13:25
1、题目:在微软亚洲研究院上班,大家早上来的第一件事是干啥呢?查看邮件?No,是去水房拿饮料:酸奶,豆浆,绿茶、王老吉、咖啡、可口可乐……(当然,还是有很多同事把拿饮料当做第二件事)。
管理水房的阿姨们每天都会准备很多的饮料给大家,为了提高服务质量,她们会统计大家对每种饮料的满意度。一段时间后,阿姨们已经有了大批的数据。某天早上,当实习生小飞第一个冲进水房并一次拿了五瓶酸奶、四瓶王老吉、三瓶鲜橙多时,阿姨们逮住了他,要他帮忙。
从阿姨们统计的数据中,小飞可以知道大家对每一种饮料的满意度。阿姨们还告诉小飞,STC(Smart Tea Corp.)负责给研究院供应饮料,每天总量为V。STC很神奇,他们提供的每种饮料之单个容量都是2的方幂,比如王老吉,都是23=8升的,可乐都是25=32升的。当然STC的存货也是有限的,这会是每种饮料购买量的上限。统计数据中用饮料名字、容量、数量、满意度描述每一种饮料。
那么,小飞如何完成这个任务,求出保证最大满意度的购买量呢?
2、分析:
问题可以这样理解:假设现在仅仅购买一种饮料,那么我们可以求出此时不同购买量的满意程度,然后再添加一种饮料,添加这种饮料与原来的那种饮料有很多的购买组合,求出此时所有符合要求组合的满意程度,简单来讲:
3、代码与执行结果(动态规划):
#include <iostream>using namespace std;#define N 7//饮料种类int V=64;//饮料的总量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};//各种饮料的满意度struct Beverage//饮料结构体{ int volumn; int maxOffer; int satisfication;};//动态规划算法void DP(Beverage* b,int n){ int** M=new int*[V+1];int*** pur=new int**[V+1];//记录每种饮料的购买数量 for(int i=0;i<=V;++i){ M[i]=new int[n];pur[i]=new int*[n];}for(i=0;i<=V;i++)for(int j=0;j<n;j++){pur[i][j]=new int[n];}/* 仅仅购买第n种饮料的购买方案 */ for(i=0;i<=V;++i) { if(i/b[n-1].volumn>b[n-1].maxOffer){ M[i][n-1]=b[n-1].satisfication*b[n-1].maxOffer;pur[i][n-1][n-1]=b[n-1].maxOffer;} else{ M[i][n-1]=b[n-1].satisfication*(i/b[n-1].volumn);pur[i][n-1][n-1]=i/b[n-1].volumn;} }/*边界条件初始化*/ for(i=0;i<=V;++i) for(int j=0;j<n-1;++j) M[i][j]=-999;/*顺次添加余下的各种饮料,每次添加一种,构建最优方案*/ for(int j=n-2;j>=0;--j) { for(int i=0;i<=V;++i) { for(int k=0;k<=b[j].maxOffer;++k) { if(b[j].volumn*k<=i) { if(b[j].satisfication*k+M[i-b[j].volumn*k][j+1]>M[i][j]) { M[i][j]=b[j].satisfication*k+M[i-b[j].volumn*k][j+1]; pur[i][j][j]=k;for(int m=j+1;m<n;m++){ pur[i][j][m]=pur[i-b[j].volumn*k][j+1][m];} } } } } }/*测试代码*//*for(i=0; i<V+1; i++){for(j=0; j<n; j++){printf("%3d ",M[i][j]);}printf("\n");}*/cout<<"最佳满意度为:"<<M[V][0]<<endl<<endl;cout<<"分配方案为:"<<endl;for(i=0;i<n;i++){cout<<"第 "<<i+1<<" 种饮料购买: ";cout<<pur[V][0][i]<<" 瓶"<<endl;}cout<<endl;system("pause"); return ;}int main(){ Beverage* beve=new Beverage[N];for(int i=0;i<N;i++){beve[i].maxOffer=c[i];beve[i].volumn=v[i];beve[i].satisfication=h[i];} DP(beve,N); return 0; }
4、简单一点的想法:
应该在不超过最大购买数量的限制下,尽可能的购买 满意度/单位饮料 大的饮料。这样就简单明了多了。
举例来讲:
代码中各种饮料的 满意度/单位饮料分别为:
10~7.5~3.125~15~3.75~3.75~6.25
所以各种饮料的购买优先权分别为:
2~3~7~1~5~6~4
对照上面的code以及result可知分析无误,上下两部分可以相互佐证。
5、查找表法code(动态规划的递归形式)
#include <iostream>#define MAXV 100#define MAXT 20#define INF 0x7fffffff#define N 7using namespace std;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 opt[MAXV+1][MAXT+1]; // 记录每种饮料购买数量int opt_num[MAXV+1][MAXT+1];// 每种饮料的容量int VV[MAXT];// 每种饮料的容量上限(购买上限)int CC[MAXT];// 每种饮料的满意度int HH[MAXT];// 每种饮料的实际购买量int BB[MAXT];int T;int Cal1(int V, int type){// 最后一种饮料if (type == T){if (V==0)return 0;elsereturn -INF;}if (V < 0)return -INF;else if(V==0)return 0;else if(opt[V][type] != -1)return opt[V][type];int ret = -INF;for (int i = 0; i <= CC[type]; i++){int temp = Cal1(V-i*VV[type], type + 1);if(temp != -INF){temp += HH[type]*i;if (temp > ret){// 记录购买V升饮料,type类型的饮料的数量。opt_num[V][type] = i;ret = temp;}}}return opt[V][type] = ret;}int main(){// 饮料总数int totle;// 总共的购买量T=N;totle=64;for (int i=0; i <= T-1; i++){VV[i] = v[i]; // 饮料的容量CC[i] = c[i]; // 容量HH[i] = h[i]; // 满意度}memset(opt, -1, sizeof(opt));int r = Cal1(totle, 0);// 下面输出每种饮料的实际供应量。 cout << "0:" <<opt_num[totle][0] << endl;// 第0种饮料的数量(单位:个)int k = opt_num[totle][0];// t是饮料总供应量(单位:升)int mm = totle;// 依次计算第1种到第T-1种饮料的实际供应量for (i = 1; i <= T; i++){// mm-k*VV[i-1]是剩余饮料供应量(单位:升)int temp = opt_num[mm - k*VV[i-1]][i];cout << i << ":"<< temp << endl;mm -=k*VV[i-1];// k保存当前饮料供应量k = temp;}cout << "最大的满意度:";cout << r <<endl<<endl;system("pause");return 0;}
参考自http://snprintf.net/archives/442
上下对比可知算法的正确性
- 编程之美——饮料供货
- 编程之美——饮料供货
- 编程之美 - 饮料供货
- [编程之美]饮料供货
- 编程之美:饮料供货
- 饮料供货@编程之美
- 编程之美 - 饮料供货
- 编程之美之饮料供货问题
- 编程之美之饮料供货
- 《编程之美》1.6 饮料供货
- 编程之美1.6 饮料供货
- 编程之美:第一章 1.6饮料供货
- 《编程之美》1.6 饮料供货 读书笔记
- 编程之美-饮料供货方法整理
- 编程之美读书笔记-饮料供货
- 《编程之美》1.6 饮料供货——贪心解法证明
- 《编程之美》读书随笔之六:饮料供货
- 编程之美:第一章游戏之乐-饮料供货问题
- 不是技术牛人,如何拿到国内IT巨头的Offer (转载)
- HDU2115 I Love This Game
- poj 1182 食物链
- 中南大ACM月赛:CSU Monthly 2013 Aug
- poj3176 cow bowling
- 编程之美——饮料供货
- OCP-1Z0-053-V13.02-517题
- Android JNI使用方法
- core dump
- 代码的坏味道
- deep learning toolbox学习4之CNN
- unity 坐标系统
- linux多线程编程,你还在用sleep么?用pthread
- 约瑟夫问题