没有人没抢过红包吧…… 这里给出N个人之间互相发红包、抢红包的记录,请你统计一下他们抢红包的收获。

输入格式:

输入第一行给出一个正整数N(≤10​4​​),即参与发红包和抢红包的总人数,则这些人从1到N编号。随后N行,第i行给出编号为i的人发红包的记录,格式如下:

KN​1​​P​1​​⋯N​K​​P​K​​

其中K(0≤K≤20)是发出去的红包个数,N​i​​是抢到红包的人的编号,P​i​​(>0)是其抢到的红包金额(以分为单位)。注意:对于同一个人发出的红包,每人最多只能抢1次,不能重复抢。

输出格式:

按照收入金额从高到低的递减顺序输出每个人的编号和收入金额(以元为单位,输出小数点后2位)。每个人的信息占一行,两数字间有1个空格。如果收入金额有并列,则按抢到红包的个数递减输出;如果还有并列,则按个人编号递增输出。

输入样例:

10
3 2 22 10 58 8 125
5 1 345 3 211 5 233 7 13 8 101
1 7 8800
2 1 1000 2 1000
2 4 250 10 320
6 5 11 9 22 8 33 7 44 10 55 4 2
1 3 8800
2 1 23 2 123
1 8 250
4 2 121 4 516 7 112 9 10

输出样例:

1 11.63
2 3.63
8 3.63
3 2.11
7 1.69
6 -1.67
9 -2.18
10 -3.26
5 -3.26
4 -12.32

分析:

这是和之前的德才论一样类型的题目,给出大量数据,然后按一定的规则排序。

具体考点:结构体,结构体指针,qsort排序,对于浮点数误差的理解。

大的框架我是完全能写出来的。

但细节上出了问题。

排序函数参数cmp

int cmp(const void *a,const void *b)
{struct people *A = (struct people *)a;struct people *B = (struct people *)b;if(fabs(A->mon>B->mon)>=1e-15){if(A->mon>B->mon) return -1;else if(A->mon<B->mon)  return 1;}//   if(A->redc>B->redc)    return -1;
//  else if(A->redc < B->redc)  return 1;
//  if(A->id > B->id)  return 1;
//  else if(A->id < B->id)  return -1;
}

起初知识两行指针赋值+三对排序。但结果和案例不同。开头三位是1,8,2。但答案是1,2,8。经反复的注释,控制变量思想,发现应该是第三重排序,也就是id来控制2在8的前面,但有没有这段代码都一样,也就是说明没有起作用。

思考认为,或许是double的误差,以前见到过,是说double不能简单地说==/!= , 因为他的有效位数一定,而之后位就会有波动。于是我怀疑,对于2和8的排序,或许根本没有进入第三重,而在第一重就因为所谓的误差走了return的路。

那么,不妨承认误差。这才有了上面的代码。

来源:https://blog.csdn.net/Rex_WUST/article/details/89219529

我便仿照这修改,如上。却发现之后的排序却变得一团糟。似乎这样写不行。

于是,这就想办法消除误差。发现题中最后输出的都是两位小数。我就想,或许实现对浮点数保留至2位在进行比较,不就行了吗。说动手就动手。

我学习了这位老师的思路:https://blog.csdn.net/weixin_42643216/article/details/100788103

便补充

for(i=1;i<=N;i++)
{if(money[i].mon>0){f = money[i].mon + 0.005;temp = f*100;f = 1.0*temp/100;money[i].mon = f;    }}

他确实起到了一些作用,但这个方法仅适用于正数,我的负数四舍五入,最后结果和理论输出偏了0.01.于是pta判断还是错误。

然后我偷鸡着改了改,上述操作只针对正数,然后就AC了。

附上代码:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
struct people{int id;double mon;int redc;
}money[20000],t;int cmp(const void *a,const void *b)
{struct people *A = (struct people *)a;struct people *B = (struct people *)b;if(A->mon>B->mon) return -1;else if(A->mon<B->mon)  return 1;if(A->redc>B->redc)  return -1;else if(A->redc < B->redc)  return 1;if(A->id > B->id)  return 1;else if(A->id < B->id)  return -1;
}int main()
{int i,N,id,mon,n,j,temp;double f;scanf("%d",&N);for(i=1;i<=N;i++){money[i].mon = 0;money[i].redc = 0;money[i].id = i;}for(i=1;i<=N;i++){scanf("%d",&n);for(j=1;j<=n;j++){scanf("%d %d",&id,&mon);money[i].mon -= 1.0*mon/100;money[id].mon += 1.0*mon/100;money[id].redc++;} }for(i=1;i<=N;i++){if(money[i].mon>0){f = money[i].mon + 0.005;temp = f*100;f = 1.0*temp/100;money[i].mon = f;  }}qsort(money+1,N,sizeof(struct people),cmp);for(i=1;i<=N;i++){printf("%d %.2lf\n",money[i].id,money[i].mon);}return 0;
}

说来都是缘。就在昨天下午,看了看翁恺老师的C语言进阶课,关于浮点数的知识。

这又给了我新的想法。

上课笔记

浮点运算的精度a = 1.234f        若只写1.234  ,则默认double,只有自己加上标注f/F,才为float。案例a = 1.234fb = 1.123fc = a+b;if(c==2.357) printf----实际上,判断发现c!=2.357.因为浮点数是有误差的。
可能真正的值是2.3579999321【可见,在一些题目,或日常生活中,比u人银行存钱。就不能有浮点数表达。因为他会在暗中对误差进行累计。造成糟糕的结果。那么怎么处理呢?】
【可以先在计算时,把他们化成整型。比如算1.23元时,可以先写成123分】

情况已经很明朗了。我就陷入了浮点误差累计的深渊。

刚才按上面思路改了下。成功了,比原来也简单了。

改动:1.删除了浮点去位操作     2.结构体里的mon用int定义   3.每次累加时,直接加的分(话说题目本就给的分,是在暗示我?)

4.排序时也用的int的mon,只在最后输出时,才 printf("%d %.2lf\n",money[i].id, (double)money[i].mon / 100 );

很高兴,这下全弄明白了。

PTA题目:7-9 抢红包 (25分)相关推荐

  1. L2-009 抢红包 (25 分)(C语言)(排序)

    题目 L2-009 抢红包 (25 分) 没有人没抢过红包吧-- 这里给出N个人之间互相发红包.抢红包的记录,请你统计一下他们抢红包的收获. 输入格式: 输入第一行给出一个正整数N(≤10 4 ),即 ...

  2. PTA秀恩爱分得快 (25分)

    PTA秀恩爱分得快 (25分) 古人云:秀恩爱,分得快. 互联网上每天都有大量人发布大量照片,我们通过分析这些照片,可以分析人与人之间的亲密度.如果一张照片上出现了 K 个人,这些人两两间的亲密度就被 ...

  3. C语言 7-7 抢红包 (25分)

    7-7 抢红包 (25分 题目 代码块 题目 没有人没抢过红包吧-- 这里给出N个人之间互相发红包.抢红包的记录,请你统计一下他们抢红包的收获. 输入格式: 输入第一行给出一个正整数N(≤10​4), ...

  4. 【CCCC】L2-009 抢红包 (25分),,间接排序,比较double大小

    problem L2-009 抢红包 (25分) 没有人没抢过红包吧-- 这里给出N个人之间互相发红包.抢红包的记录,请你统计一下他们抢红包的收获. 输入格式: 输入第一行给出一个正整数N(≤10 ​ ...

  5. 题目:L2-031 深入虎穴 (25 分)

    题目:题目详情 - L2-031 深入虎穴 (25 分) (pintia.cn) 大意 已知情报藏在一个地下迷宫里,迷宫只有一个入口,里面有很多条通路,每条路通向一扇门.每一扇门背后或者是一个房间,或 ...

  6. 7-4 抢红包 (25分)

    7-4 抢红包 (25分) 没有人没抢过红包吧-- 这里给出N个人之间互相发红包.抢红包的记录,请你统计一下他们抢红包的收获. 输入格式: 输入第一行给出一个正整数N(≤10​4​​),即参与发红包和 ...

  7. PTA 03-树1 树的同构 (25分)

    题目地址 https://pta.patest.cn/pta/test/15/exam/4/question/711 5-3 树的同构   (25分) 给定两棵树T1和T2.如果T1可以通过若干次左右 ...

  8. PTA 哈利·波特的考试 (25分)

    哈利·波特的考试 (25分) 题目链接 问题描述: 哈利·波特要考试了,他需要你的帮助.这门课学的是用魔咒将一种动物变成另一种动物的本事.例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe ...

  9. PTA 7-3 插入排序还是归并排序 (25分)

    c++sort函数和equal函数的应用 一. sort函数 sort函数包含在头文件为#include的c++标准库中,调用标准库里的排序方法可以实现对数据的排序. sort(first,last, ...

最新文章

  1. 数据科学家最常用的十种算法
  2. 分布式开放消息系统(RocketMQ)的原理与实践
  3. boost::math::inverse_chi_squared用法的测试程序
  4. C++基础知识总结(一)
  5. 第6章 数据库索引优化
  6. cent6.8 nginx php,CentOS 6.8 安装Nginx
  7. 【BZOJ1412】【codevs2351】狼和羊的故事,最小割
  8. GridView的RowCommand事件中取得行索引 技巧
  9. oracle 重设基线,Oracle SQL执行计划基线总结(SQL Plan Baseline)
  10. 7.携程架构实践 --- IaaS & PaaS
  11. 威纶通触摸屏可以解密吗_【实例】西门子PLC变频器和触摸屏综合应用
  12. python怎么设置背景音乐_怎么设置背景音乐?
  13. 自有项目Iframe嵌入ThingJS物联网可视化项目代码解析
  14. 金蝶——“免、抵、退”税操作说明及帐务处理
  15. 张亚勤退休百度:一个耐人寻味的微笑
  16. OpenCV中Rect的一些神奇用法
  17. Python画四张子图-导入数据
  18. PO模式项目实战思路分析
  19. 信用评分卡Credit Scorecards (1-7)
  20. 基于matlab的RS编译码仿真,从底层原理分析RS编译码的实现过程

热门文章

  1. 云时代的应用性能管理(APM)
  2. ios 代码例子 卷边的翻书效果
  3. 计算机制图的特点和原理,计算机地图制图原理、特点及发展趋势
  4. dvd在线租赁问题 matlab,DVD在线租赁服务管理模型
  5. 识别连笔字的软件_在线手写文字识别软件快速代抄
  6. 在64位的Linux系统使用gcc的-m32选项编译32位的程序得到了多余的代码(多余指令call和add)、有多余的.text.__x86.get_pc_thunk.ax
  7. 止血、回血 苏宁易购正在复苏路上
  8. 保弘实业|大学生理财必须做到这四点
  9. QQ返利当当特惠活动(10.26~11.4)
  10. [扫盲教程]——Mac 新手最容易犯的几项错误