【HDU 2507】【ACM-ICPC算法基础训练教程 题1-6】 迷瘴(贪心)

题目分析:

  1. 由于每瓶药水体积相同,要求体积最大等同于瓶数最多。
  2. 要求浓度不大于W%,所以我们需要从浓度较低的药水开始添加,直到浓度刚好不大于W%。
  3. 一瓶浓度为20%的药水和一瓶浓度为30%的体积相同的药水混合,浓度为25% = (20%+30%)/2。
  4. 体积相同则混合后浓度与体积无关,3瓶以上同理。

解题思路:

  1. 将药水浓度a[]排序,优先添加低浓度药水。
  2. 当添加了第1~i瓶药水时,药水浓度为P/i,(P = a[1]~a[i]之和)。
  3. 如果当前药水浓度恰好超过了要求浓度W,则退回一步,i--。此时浓度正好不大于W。
  4. 输出体积i*v和浓度P/i。

代码如下:

#include <bits\stdc++.h>
using namespace std;
typedef long long ll;
int a[105];
int main(){
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	int n,v,m;
	while(t--){
		cin >> n >> v >> m;
		for(int i = 1;i <= n; ++i){
			cin >> a[i];
		}
		//按浓度排序所有药水,从浓度较低的开始添加 
		sort(a+1,a+1+n);
		int i;
		a[0] = 0; 
		//添加第1~i瓶药水,当前药水浓度为a[1]加到a[n]除以i 
		for(i = 1;i <= n; ++i){
			//将浓度加起来 
			a[i] += a[i-1];
			//如果浓度大于要求浓度,则撤回当前这瓶药水
			// 实际表达式为a[i]/i > m
			//a[i]不为浮点型除法会丢失精度,故用以下表达式 
			if(a[i] > m*i) break;
		}
		i--; //撤回一步,保证浓度小于等于要求浓度m 
		if(i == 0){
			printf("0 0.00\n");
		}else{
			printf("%d %.2lf\n" , i*v,1.0*a[i]/i/100);
		}
	} 
	return 0;
} 
posted @ 2019-09-02 13:51  ninding  阅读(201)  评论(0编辑  收藏  举报