编程之美之饮料供货

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

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

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

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

我们先把这个问题“数学化”一下吧。

假设STC共提供n种饮料,用(SiViCiHiBi)(对应的是饮料名字、容量、可能的最大数量、满意度、实际购买量)来表示第i种饮料(= 0, 1,…, n-1),其中可能的最大数量指如果仅买某种饮料的最大可能数量。

分析:此题是一个典型的多重背包问题,把问题转化为背包模型就是:已知有n种物体,第i个物体共有Ci个,重量是Vi,价值是Hi,背包的总容量是W,求背包可装物体的最大价值。

动态转移方程:dp[i][j]表示第i个物体到最后一个物体可被选择,背包剩余容量为j,假设当前第i个物体取了k个放入背包(0<=k<=C[i]),则

dp[i][j] = max(dp[i+1][j-k*V[i]]+k*H[i]).其中,i从n-1开始到0结束,对每个i,j从1到W,则dp[0][W]即为最后的结果,具体代码如下:

#include<iostream>
#include<memory.h>
using namespace std;

/**
 * W:饮料总容量的最大上限;N:饮料的种类;C:每种饮料的个数;H:每种饮料的满意度;V:每种饮料的容量
 * 求:在满足最大容量<=W的前提下,如何购买饮料获得的满意度最大
*/
int Cal(int W,int N,int* C,int* H,int* V)
{
	if(W <=0 || N<=0 || C== NULL|| H==NULL || V==NULL)return 0;
	int i,j,k;
	int** dp = new int* [N+1];
	for(i=0;i<=N;i++)
	{
		dp[i] = new int[W+1];
	}
	memset(dp[N],0,sizeof(int)*(W+1));
	for(i=N-1;i>=0;i--)
	{
		for(j=1;j<=W;j++)
		{
			dp[i][j] = 0;
			for(k=0;k<=C[i];k++)
			{
				if(j >= k*V[i])
				{
					dp[i][j] = max(dp[i][j],dp[i+1][j-k*V[i]]+k*H[i]);
				}
				else break;
			}
		}
	}
	int res = dp[0][W];
	for(i=0;i<=N;i++)delete[] dp[i];
	delete[] dp;
	return res;
}

int main()
{
	int w,n,i;
	while(cin >> w >> n)
	{
		int* C = new int[n];
		int* H = new int[n];
		int* V = new int[n];
		for(i=0;i<n;i++)cin >> C[i] >> H[i] >> V[i];
		cout << Cal(w,n,C,H,V)<< endl;
		delete[] C;
		delete[] H;
		delete[] V;
	}
	return 0;
}

如有错误,请指正,谢谢

编程之美之饮料供货

时间: 2024-08-06 01:53:52

编程之美之饮料供货的相关文章

第1章 游戏之乐——饮料供货

饮料供货 1. 问题描述 在微软亚洲研究院上班,大家早上来的第一件事是干啥呢?查看邮件?No,是去水房拿饮料:酸奶,豆浆,绿茶.王老吉.咖啡.可口可乐……(当然,还是有很多同事把拿饮料当做第二件事). 管理水房的阿姨们每天都会准备很多的饮料给大家,为了提高服务质量,她们会统计大家对每种饮料的满意度.一段时间后,阿姨们已经有了大批的数据.某天早上,当实习生小飞第一个冲进水房并一次拿了五瓶酸奶.四瓶王老吉.三瓶鲜橙多时,阿姨们逮住了他,要他帮忙. 从阿姨们统计的数据中,小飞可以知道大家对每一种饮料的

编程之美-分层遍历二叉树

问题:给定一个二叉树,要求按分层遍历该二叉树,即从上到下按层次访问该二叉树(每一层将单独输出一行),每一层要求访问的顺序为从左到右,并将节点依次编号.那么分层遍历如图的二叉树,正确的输出应该为: <span style="font-size:14px;">1 2 3 4 5 6 7 8</span> 书中还给出了问题2:打印二叉树中的某层次的节点(从左到右),其中根结点为第0层,成功返回true,失败返回false 分析与解法 关于二叉树的问题,由于其本身固有的

读书问题之《编程之美》 -----12061161 赵梓皓

我阅读的书是<编程之美> 刚开始的时候阅读序,就觉得控制cpu利用率这个问题很好玩,所以重点看了这部分和解决办法,问题也都大部分是这部分的.那么问题就来了(挖掘机技术xxx?中国山东找蓝翔) 咳咳,问题在下面: 1.关于问题的提出.(也是一点点建议) 本书的主要内容是告诉读者如何思考问题和解决问题.但是提出问题也是很重要的,正如爱因斯坦所说“提出一个问题往往比解决一个问题更重要”,很多面试题(比如井盖为啥是圆的)我觉得正常人很少会想到.所以,这个问题是怎么想出来的...我很好奇.也希望作者能够

《编程之美》3.6判断链表是否相交之扩展:链表找环方法证明

先看看原题:<编程之美>3.6编程判断两个链表是否相交,原题假设两个链表不带环. 为了防止剧透使得没看过原题目的读者丧失思考的乐趣,我把最好的解法隐藏起来.由于这个问题本身的解答并不是本文的重点,扩展问题也采用这种形式呈现. 注:位于(*)符号之间的文字出自于:http://blog.csdn.net/v_july_v/article/details/6447013,作者v_JULY_v. 用指针p1.p2分别指向两个链表头,不断后移:最后到达各自表尾时,若p1==p2,那么两个链表必相交 用

编程之美之买票找零

题目:假设有2N个人在排队买票,其中有N个人手持50元的钞票,另外有N个人手持100元的钞票,假设开始售票时,售票处没有零钱,问这2N个人有多少种排队方式,不至使售票处出现找不开钱的局面? 分析:队伍的序号标为0,1,...,2n-1,并把50元看作左括号,100元看作右括号,合法序列即括号能完成配对的序列.对于一个合法的序列,第0个一定是左括号,它必然与某个右括号配对,记其位置为k.那么从1到k-1.k+1到2n-1也分别是两个合法序列.那么,k必然是奇数(1到k-1一共有偶数个),设k=2i

【编程之美】java实现重建二叉树

package com.cn.binarytree.utils; /** * @author 刘利娟 [email protected] * @version 创建时间:2014年7月20日 下午2:03:30 类说明: */ class Node { Node left; Node right; char chValue; Node(char chValue) { left = null; right = null; this.chValue = chValue; } } public cla

编程之美之字符串移位包含问题

[题目] 给定两个字符串s1和s2,要求判断s2是否能够被通过s1做循环移位(rotate)得到的字符串包含.例如,S1=AABCD和s2=CDAA,返回true:给定s1=ABCD和s2=ACBD,返回false. [分析] [思路一] 从题目中可以看出,我们可以使用最直接的方法对S1进行循环移动,再进行字符串包含的判断,从而遍历其所有的可能性. 字符串循环移动,时间复杂度为O(n),字符串包含判断,采用普通的方法,时间复杂度为O(n*m),总体复杂度为O(n*n*m). 字符串包含判断,若采

读《编程之美》读后感

读完<编程之美>后,我觉得这并不是简简单单的一本有关于编程的书,本书强调的不仅仅是程序或者考题本身,而是思维.这就和小学时看到数学奥林匹克竞赛的题一样,重要的不是套路或者定式,而在于独立思考时被自己激活的无数脑细胞.对于程序,也是一样,思维,才是程序的精髓所在.正如作者所言,书中展现的题目和分析,犹如海滩上美丽的石子和漂亮的贝壳那样,反映出造化之美,编程之美.该书的目的不仅在于揭开微软面试的神秘面纱,更是鼓励更多的编程爱好者从中收获自己的想法,开阔自己的眼界.作者更希望让面试者和被面试者都能够

求二进制数中1的个数(编程之美)

求二进制数中1的个数 继京东618店庆时买的<编程之美>这本书,翻了翻,发现里面的题还是挺有意思的,看起来我们觉得很简单的题目,解法却有很多很多种,真是一个比一个巧妙,于是,决定记录一下. 书中的题目如下 对于一个字节(8bit)的无符号数,求其二进制表示中"1"的个数,要求算法的执行效率尽可能高. 就像书中给我们说的一样,我们一般人可能想到的解决方法如下 int countOne(int n){ int count=0; while(n){ if(n%2==1){ cou