喝饮料

136 阅读2分钟

题目描述

商店里有n种饮料,第i种饮料有mi毫升,价格为wi。 小明现在手里有x元,他想喝尽量多的饮料,于是向你寻求帮助,怎么样买才能喝的最多。 请注意,每一种饮料都可以只买一部分。

输入描述:

有多组测试数据。 第一行输入两个非负整数x和n。 接下来n行,每行输入两个整数,分别为mi和wi。 所有数据都不大于1000。 x和n都为-1时程序结束。

输出描述:

请输出小明最多能喝到多少毫升的饮料,结果保留三位小数。

示例

输入
233 6 
6 1
23 66
32 23
66 66
1 5
8 5
-1 -1

输出
136.000

思路

  1. 小明要想喝的最多饮料的话,应优先选择性价比最高的,即每毫升的价格最低的饮料先喝。

  2. 利用sort排序,比较每毫升的饮料价格,从低到高排序。然后一个一个喝,直到金额为0为止,这样才能保证喝到最多饮料。

具体实现

#include<bits/stdc++.h>
using namespace std;

struct node{
	double mi,wi; //mi为毫升 wi表示价格
}p[100]; 
bool cmp(struct node a, struct node b){
	return a.wi/a.mi < b.wi/b.mi; //每毫升的价格按从小到大排序 
} 

int main(){
	int x,n; //x表示金额总数,n表示饮料总数
	while(cin>>x>>n){  
		if(x == -1 && n == -1) break;
		for(int i=0; i<n; i++) //输入饮料毫升和价格
			cin>>p[i].mi>>p[i].wi;
		sort(p,p+n,cmp); //排序 
		
		double ans=0; //存放买的饮料的毫升 
		for(int i=0; i<n; i++){
			if(x>=p[i].wi){ //如果钱够买这款饮料 
				ans+=p[i].mi;
				x-=p[i].wi; 
			}else{ //如果钱不够买这款饮料 
				ans = p[i].mi * x/p[i].wi;
				break; //金额已花完 
			} 
		}
		printf("%.3lf\n",ans); 
	}
	return 0;
}

小结

  • 贪心算法:追求当前的最优解,从而得到全局最优解。即不从整体最优加以考虑,只做出在某种意义上的局部最优解。

  • 使用贪心算法的时候,往往需要先按某个特性排好序,也就是说贪心一般和sort一起使用。