描述一下自己:自己没控制好时间 ,没有提前练习;
问题描述:
n个人吃饭,总共花费m钱数,n个人分别带a0,a1,....钱,计算怎么出钱使得
这n个人出的钱的方差最小。输出方差即可。
输入:
10 30
2 1 3 4 5 6 7 8 9 10
输出:
0.7928
忘了输入输出的格式要求,但是可以肯定的是,他说明了一个人出的钱可以不是一分钱的整数倍,就是说,double类型,然后不用考虑人民币的整数情况。
//蓝桥杯2018年第九届 c/c++ A组算法 第十题
#include<stdio.h>
#include<math.h>
#define N 1000
int main(){
int i,j,n,m,coutpoor=0,coutave;
double a[N],b[N],ave,sum1=0,temp,sum2=0;
scanf("%d %d",&n,&m);
ave=m*1.0/n;
for(i=0;i<n;i++){ //输入n个人手上的现金
scanf("%lf",&a[i]);
if(a[i]<=ave){ //与此同时将少于平均钱 的 人 挑出来,因为他们必须得倾其所有,使得方差变小
b[coutpoor++]=a[i];
}
}
for(i=0;i<n;i++) //将他们的钱由小到大排序
for(j=n-1;j>i;j--){ //懒得去写更高效率的排序算法了
if(a[j]<a[j-1]){
temp=a[j];
a[j]=a[j-1];
a[j-1]=temp;
}
}
//for(i=0;i<n;i++){
// printf("%lf ",a[i]);
//}
if(coutpoor==0){
for(i=0;i<n;i++)b[i]=ave; //如果没有穷人(即大家带的钱都超过平均),则最终所出的钱放在b[N]中
sum2=0;
}
else{
for(i=0;i<coutpoor;i++)sum1=sum1+ave-b[i]; //算出 “穷人”总差值 (因为需要后面的人补额)
coutave=coutpoor; //我们总是希望让后面的人尽量 平摊 差额
for(i=coutpoor;i<n;i++){
if(a[i]<(sum1/(n-coutave)+ave)){ //去找补额的人,如果当前人选 不足以 平摊 平均差额
b[i]=a[i]; //交出你所有的钱
sum1=sum1-(a[i]-ave); //虽然不足以平摊平均差额 但是还是填补了空缺 ,此时差额变小
coutave++; //记录欠 和补 差额的人
}
else{
b[i]=sum1/(n-coutave)+ave; //如果 这个人选 “有钱” 则 直 接 补差额
}
}
for(i=0;i<n;i++){
sum2=sum2+(b[i]-ave)*(b[i]-ave); //计算方差 根号下面的sum
}
}
printf("%.4lf",sqrt(sum2/n)); //最小方差
return 0;
}
如有疑问 可以留言