10.18T6 卡精度

溶液混合2176

【问题描述】

小Y由于高考的失败,被迫服从安排到化学系。对此小Y感到很无辜,于是他的大学四年都沉浸在了虚拟时空中(Orz…),甚至连配置溶液都不会。紧接着毕业论文横空出世。新的难题困扰这小Y。小Y经过几天废寝忘食的自学,跨时代地提出某一种溶液当浓度值等于某一个值的时候,这种溶液会对人产生一种神奇的效果。于是,某个月黑风高之时,小Y溜进实验室,偷出这种溶液若干瓶,决定自己配置一些神奇的溶液。当然,实验室的溶液浓度各不相同,怎么配成小Y需要的浓度呢……这于小Y可是大难题。
注:假设两种溶液混合后体积不发生变化。

【输入】

第一行,一个整数N,表示小Y偷出来的溶液瓶书,N小于等于50。
第二行,N个整数Ai,表示偷出来第I瓶溶液的浓度,Ai小于等于100.
第三行,N个整数Bi,表示偷出来第I瓶溶液的体积,Bi小于等于1000
第四行,一个整数,表示小Y想要的浓度。

【输出】

一个实数,它最多可以配成这种浓度的溶液多少体积,请保留5位小数。

【样例输入】

3

50 49 51

395 971 964

50

【样例输出】

2330.00000

 

【题目分析】贪心法

    为了得到更多的溶液,首先把所有溶液倒在一起。

    当然可能浓度不一定满足要求。于是要倒出一些原先加的溶液使得浓度满足要求。

    显然,我们要倒掉尽可能少的溶液使得剩下溶液的浓度满足要求。

①若当前浓度大于要求的浓度:那么倒掉一些比当前浓度大的溶液,就能使溶液浓度下降。倒掉等体积的溶液,倒掉的溶液的浓度越大,浓度下降得越多。

    因此我们得到算法:从浓度大的溶液开始一点一点倒,直到倒到满足要求,如果倒光了也不能满足要求就输出0,否则输出倒到满足要求时还剩下的溶液体积。

    程序实现时,显然不可能“一点一点”倒,一开始应该一瓶一瓶倒,当发现倒掉某一瓶之后浓度下降到要求浓度之下那么,那么说明这瓶只要倒掉一部分,解一个方程,数学演算省略。

②若浓度小于要求的做法类似,在此省略。

【算法步骤】

①读入数据,计算全部溶液混合后的浓度nc;

②把溶液按浓度从小到大排序;

③若nc>c则从最浓的开始倒出;否则从最低的开始倒出

 

 

 

code:

 1 #include<iostream>
 2 #include<iomanip>
 3 using namespace std;
 4 double a[60],b[60],ans=0,c,sum=0,rz=0,cn;
 5 int main()
 6 {  int i,j,k,n;
 7    cin>>n;
 8    for(i=1;i<=n;i++)cin>>a[i];//浓度 
 9    for(i=1;i<=n;i++){cin>>b[i];sum+=b[i];rz+=b[i]*a[i];}
10    cn=rz/sum;//全部混合后溶液的浓度 
11    cin>>c;//想要的浓度 
12    for(i=1;i<=n-1;i++)//按照浓度从小到大排序 
13       for(j=i+1;j<=n;j++)
14          if(a[i]>a[j]){swap(a[i],a[j]);swap(b[i],b[j]);}
15    j=n;
16    while(cn>c)//浓度大于想要的浓度c 
17    {  double x;
18       x=double((rz-sum*c)/(a[j]-c));//计算应倒掉浓度为a[j]的体积 
19       if(x<=b[j]){sum-=x;break;}
20       sum-=b[j];rz-=b[j]*a[j];
21       cn=rz/sum;
22       j--; 
23    }
24    i=1;
25    while(cn<c)//浓度小于想要的浓度c 
26    {  double x;
27       x=(sum*c-rz)/(c-a[i]);
28       if(x<=b[i]){sum-=x;break;}
29       sum-=b[i];rz-=b[i]*a[i];
30       cn=rz/sum;
31       i++; 
32    }
33    cout<<fixed<<setprecision(5)<<sum<<endl;
34    return 0;
35 }

over

posted @ 2018-10-18 22:03  saionjisekai  阅读(90)  评论(0编辑  收藏  举报