1223排队接水
难度:普及-
题目类型:贪心
提交次数:1
涉及知识:贪心,排序
题目描述
有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小。
输入输出格式
输入格式:
输入文件共两行,第一行为n;第二行分别表示第1个人到第n个人每人的接水时间T1,T2,…,Tn,每个数据之间有1个空格。
输出格式:
输出文件有两行,第一行为一种排队顺序,即1到n的一种排列;第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。
代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<vector> 4 #include<cstdio> 5 using namespace std; 6 struct stu{ 7 int num; 8 int w; 9 stu(int nn, int ww):num(nn), w(ww){} 10 }; 11 vector<stu>v; 12 bool com(stu a, stu b){ 13 return a.w <= b.w; 14 } 15 int main(){ 16 int n; 17 cin>>n; 18 int i; 19 for(i = 1; i <= n; i++){ 20 int num; 21 cin>>num; 22 v.push_back(stu(i, num)); 23 } 24 sort(v.begin(), v.end(), com); 25 for(i = 0; i < v.size(); i++) 26 cout<<v[i].num<<" "; 27 cout<<endl; 28 float sum = 0; 29 for(i = 0; i < v.size(); i++) 30 sum += v[i].w*(n-i-1); 31 /*map<int, int>::iterator iter; 32 for(iter = a.begin(); iter != a.end(); iter++) 33 { 34 cout<<iter->first<<" "<<iter->second<<endl; 35 }*/ 36 printf("%f", sum); 37 double ans; 38 ans = sum/n; 39 printf("%.2lf", ans); 40 return 0; 41 }
备注:
很简单的一道题,贪心选择策略就是时间越短的人越往前排,本来想借机熟悉一下map。不过实在多此一举了。。注释部分作参考吧。
不过这道题帮我弥补了一个很大的知识点漏洞,即单精度和双精度问题。我开始时用的float,结果会有很小的误差,改成double就对了。上网查资料,发现阶码啊,尾码啊,指数位都不记得了。就复习了一下。以下内容摘自博客。
(浮点)数值 = 尾数 × 底数 ^ 指数,(附加正负号)---------------- F.2
于是,float的指数范围为-127~128,而double的指数范围为-1023~1024,并且指数位是按补码的形式来划分的。其中负指数决定了浮点数所能表达的绝对值最小的数;而正指数决定了浮点数所能表达的绝对值最大的数,也即决定了浮点数的取值范围。
float的范围为-2^128 ~ +2^128,也即-3.40E+38 ~ +3.40E+38;double的范围为-2^1024 ~ +2^1024,也即-1.79E+308 ~ +1.79E+308。
float和double的精度是由尾数的位数来决定的。浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,由于它是不变的,故不能对精度造成影响。
float:2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字;
double:2^52 = 4503599627370496,一共16位,同理,double的精度为15~16位。
是有效数字,不是小数点后几位,这块我一直搞错了。。。float能保证精度的只有6位有效数字,所以整数部分稍大一些就挂了。