rqnoj 495 化学课配制溶液

原题: https://www.rqnoj.cn/problem/495

//rqoj495 
//给出不同溶液的浓度Ai和体积Bi,问 最多能配出多大体积的浓度W的溶液。Ai,Bi,Wi由题目给出,均为整数 
//思路:先把所有的溶液浓度由高到低排序,然后把所有的溶液都混合在一起,得到总浓度为C,总体积V三种情况: 
//    ①如果浓度C刚好等于w,即可输出体积
//    ②如果C>W,说明浓度太高,为了使体积减少量最少,我们选择 先去掉浓度最高Ci的溶液ri(设体积为Vi),假设去掉的体积为Vx
//    列出公式有:  C*V - Ci * Vx = Wi*(V-Vx),好好体会这条公式,这是关键。
//    如果求出Vx>Vi,说明去除了所有的Ci溶液还是达不到浓度Wi,我们先去除全部Ci溶液后,再查找下一个
//    如果求出Vx<=Vi,说明去除Vx就可以恰好达到浓度Wi,这时我们用V-Vx,跳出循环。  
//    ③如果C<W,过程则与②相反,先去除浓度最低的溶液..
//注意精度问题,如果浮点数比较大小的表达方式.
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
struct R 
{
	double vi;//体积 
	double ci;//浓度 
}r[51];//溶液 
int cmp(R a,R b)//浓度从大到小 
{
	return a.ci>b.ci;
}
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		double sum=0;
		double v=0;
		for(int i=0;i<n;i++)
		{
			scanf("%lf",&r[i].ci);
		}
		for(int i=0;i<n;i++)
		{
			scanf("%lf",&r[i].vi);
			sum=sum+r[i].ci*r[i].vi;//总溶质 
			v=v+r[i].vi;//总体积 
		}
		sort(r,r+n,cmp);
		double target;//所需要的目标弄度 
		scanf("%lf",&target);
		double now=sum/v;//全部混合在一起的浓度
		if(now==target){
			printf("%.5lf\n",v);
			continue;
		}else if(now<target){//浓度太低 
			int i;
			for(i=n-1;i>=0;i--)//从低浓度额开始减 
			{ 
				double tmp=v*(now-target)/(r[i].ci-target);
				if(tmp-r[i].vi>0.000001) //浮点数判断大于 
				{
					double m=r[i].vi*r[i].ci;
					sum=sum-m;
					v=v-r[i].vi;
					now=sum/v;
				}else{
					v=v-tmp;
					break;
				}
			}
			printf("%.5lf\n",v);
		}else{
			int i;
			for(i=0;i<n;i++)//从高浓度额开始减 
			{
				double tmp=v*(now-target)/(r[i].ci-target);
				if(tmp-r[i].vi>0.000001)
				{
					double m=r[i].vi*r[i].ci;
					sum=sum-m;
					v=v-r[i].vi;
					now=sum/v;
				}else{
					v=v-tmp;
					break;
				}
			}
			printf("%.5lf\n",v);
		}
	}
	return 0;
}

一开始我的想法是把所有的溶液先混合起来,如果溶度高就去减掉浓度高的溶液,那浓度高的溶液要减掉多少呢,我就去二分找最佳体积了....结果被我搞得好复杂,也过了60的数据.最后没解出来。。。看了评论区之后才明白了正确的思路,以后浓度这些我还是应该冷静下来去推 公式,不要慌。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值