按  

  被中科大软件学院二年级研究生 HCOONa 骂为“误人子弟”之后(见:《中科大的那位,敢更不要脸点么?》 ),继续“误人子弟”。

问题:

题目:(感谢 王爱学志 网友对题目给出的翻译)
    排名
题目要求:
    程序运行时间要不大于1000ms,程序的内存大小不大于32756k.
    向审题系统提交总时间是2843秒,审题系统接受的提交时间是860秒.
题目描述:
    Jackson想知道他在班级中的排名.教授已经公布班级中人的
    学号和分数的列表.计算Jackson的排名,如果他分数是最高的(包
    括和他分数一样),那么他的排名是1,如果他分数是第二高(包括
    和他分数一样的),那么他的排名是2,等等
输入:
    输入多个测试用例,以Jackson的学号为输入开始.学号是
    10000000到99999999之间的整数.之后输入所有学生的学号和分数
    .分数是0到100的整数.这个课堂上的学生数不超过1000.每个学生
    的学号是不同的.以输入学号和分数都为0表示输入结束.
输出:
    通过每个测试用例数据,在新的一行输出Jackson的班级排名
样例的输入:
    20070101
    20070102 100
    20070101 33
    20070103 22
    20070106 33
例子的输出:
    2
题目来源:
    2007省赛集训队练习赛(2)
推荐:
    ky

见 :【ACM】杭电ACM题一直WA求高手看看代码

原代码:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define max 1000
  4. /* run this program using the console pauser or add your own getch, system("pause") or input loop */
  5.  
  6. int main(int argc, char *argv[]) {
  7. int stu[max]; //学生的ID
  8. int stur[max]; //学生的成绩
  9. int rank,jack_id; //查找的ID
  10. int flag[];
  11. int i,jack,n;
  12. freopen("in.txt","r",stdin);
  13. while(scanf("%d",&jack)!=EOF){
  14. for( i= ; i<max ;i++) {
  15. stu[i]=;
  16. stur[i]=;
  17. }
  18. for( i= ; i< ;i++) {
  19. flag[i]=;
  20. }
  21. for( i= ; ;i++) {
  22. scanf("%d%d",&stu[i],&stur[i]);
  23. if(stu[i]==&&stur[i]==) break;
  24. }
  25. n=i;
  26. for( i= ; i<n ; i++) {
  27. if(jack==stu[i]) {
  28. jack_id=i;
  29. }
  30. }
  31. rank=;
  32. for( i= ; i<n ; i++) {
  33. if((stur[i]>stur[jack_id])&&(flag[stur[i]]!=)){ //找到比自己大的成绩rank++
  34. rank++;
  35. flag[stur[i]]=;
  36. }
  37.  
  38. }
  39. printf("%d\n",rank);
  40.  
  41. }
  42.  
  43. return ;
  44. }

评析:

  毛病很多。据原作者说“数据测试了好几个都没问题,可以就是WA不让过”。其实我也不清楚什么原因不过,因为没玩过。只能就其中的错误说一说。并给出改进,但同样不能保证通过,因为我不知道“ACM”的规则。

  1. #include <stdlib.h>

  不清楚做什么的,没用。

  1. #define max 1000

  明显违背公序良俗。宏名应该大写。

  1. int main(int argc, char *argv[]) {

  应该

  1. int main( void ) {

  代码这东西,你不把它写好就不可能把它写对。

  一main()到底,也是初学者常见的幼稚病,表明根本不懂得如何组织代码。(参见:将main()进行到底)

  1. int stu[max]; //学生的ID
  2. int stur[max]; //学生的成绩

  原作者显然同样不懂得如何组织数据,还处于社会主义初级阶段。
  数组尺寸为max不是不可以,但从后面的代码来看明显错了。应该是 max+1。

  1. int flag[];

  我在《品悟C》中说过,出现flag的代码,多半早就馊了。(参见:flag标志什么?哦,它标志代码馊了——(一))

  1. while(scanf("%d",&jack)!=EOF){

  这个写得还行。问题是原问题特意强调了范围,是否视为long为好?存在这样的可能性:原题的意思是把number作为long处理,把mark作为int处理。当然这只是猜测。

  1. for( i= ; i<max ;i++) {
  2. stu[i]=;
  3. stur[i]=;
  4. }

  这里写得很傻。其实只要

  1. while(scanf("%d",&jack)!=EOF){
  2. int stu[max] = {}; //学生的ID
  3. int stur[max]= {}; //学生的成绩
  4. //……
  5. }

  就可以了。显然原代码中这两个数组定义的位置不当。

  1. for( i= ; i< ;i++) {
  2. flag[i]=;
  3. }

  天知道这是在干什么,很傻很变态。

  1. for( i= ; ;i++) {
  2. scanf("%d%d",&stu[i],&stur[i]);
  3. if(stu[i]==&&stur[i]==) break;
  4. }

  这里存在越界的可能。有效成绩最多1000个,结束标志0 0 就可能是第1001个。

  从这里向后,已经看不下去了,完全不之所云。不过既然至此已经存在越界错误,也没有必要再看下去了。

  下面给出我的写法:

重构:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. typedef long num_t ;
  5. #define FN "%ld"
  6. typedef int mark_t ;
  7. #define FM "%d"
  8.  
  9. typedef
  10. struct
  11. {
  12. num_t num ;
  13. mark_t mark ;
  14. }
  15. STD;
  16.  
  17. int input( STD [] , num_t , mark_t * );
  18. int rank( STD [] , int , mark_t );
  19.  
  20. int main( void )
  21. {
  22. num_t jack_n ;
  23.  
  24. while ( scanf( FN , &jack_n ) != EOF )
  25. {
  26. STD stu[ + ] ;
  27. int sum ;
  28. mark_t jack_m ;
  29.  
  30. sum = input( stu , jack_n , &jack_m ); //输入并获得数据总数及Jack的成绩
  31. printf("%d\n" , rank( stu , sum , jack_m ) );//输出Jack的名次
  32. }
  33.  
  34. system("PAUSE");
  35. return ;
  36. }
  37.  
  38. int input( STD stu[] , num_t j_n , mark_t * p_j_m )
  39. {
  40. STD * p_ini = stu ;
  41.  
  42. while ( scanf( FN FM , &stu->num , &stu->mark ) ,
  43. stu->num != j_n ) //读入数据直到Jack的
  44. stu ++ ;
  45.  
  46. * p_j_m = stu++ -> mark ;
  47.  
  48. while ( scanf( FN FM , &stu->num , &stu->mark ) ,
  49. stu->num != || stu->mark != ) //读Jack后面的
  50. stu ++ ;
  51.  
  52. return stu - p_ini ;
  53. }
  54.  
  55. int rank( STD stu[] , int n , mark_t j_m )
  56. {
  57. int r = ;
  58. int i ;
  59.  
  60. for ( i = ; i < n ; i ++ )
  61. if ( stu[i].mark > j_m )
  62. r ++ ;
  63.  
  64. return r ;
  65. }

小结:

  input()函数中的两句while很相似,有点难看。改得更漂亮一点怕初学者看不懂,就不改了。

此外,我也不能保证我的代码一定就过,因为我从没刷过题,不清楚刷题的具体规则。

再次重构:

  根据 librazy 网友提供的信息:

没记错的话大多数评测机中long 就是long int 就是 int。一般算法竞赛中忘了时空效率考虑都是int(除了很明显需要高精度或ll的。

  以及Matrix_R  网友的意见:

不过有个小疑问,就是为什么楼主的函数声明中指针的声明方式都是清一色的[]?为了表明参数是个数组吗?我个人觉得直接用指针更好,更本质。

  再次重构代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. typedef
  5. struct
  6. {
  7. int num ;
  8. int mark ;
  9. }
  10. STD;
  11.  
  12. int input( STD * , int , int * );
  13. int rank( STD [] , int , int );
  14.  
  15. int main( void )
  16. {
  17. int jack_n ;
  18.  
  19. while ( scanf( "%d" , &jack_n ) != EOF )
  20. {
  21. STD stu[ + ] ;
  22. int sum ;
  23. int jack_m ;
  24.  
  25. sum = input( stu , jack_n , &jack_m ); //输入并获得数据总数及Jack的成绩
  26. printf("%d\n" , rank( stu , sum , jack_m ) );//输出Jack的名次
  27. }
  28.  
  29. system("PAUSE");
  30. return ;
  31. }
  32.  
  33. int input( STD * p_stu , int j_n , int * p_j_m )
  34. {
  35. STD * p_ini = p_stu ;
  36.  
  37. while ( scanf( "%d%d" , &p_stu->num , &p_stu->mark ) ,
  38. p_stu -> num != j_n ) //读入数据直到Jack的
  39. p_stu ++ ;
  40.  
  41. * p_j_m = p_stu ++ -> mark ;
  42.  
  43. while ( scanf( "%d%d" , &p_stu->num , &p_stu->mark ) ,
  44. p_stu->num != || p_stu->mark != ) //读Jack后面的
  45. p_stu ++ ;
  46.  
  47. return p_stu - p_ini ;
  48. }
  49.  
  50. int rank( STD stu[] , int n , int j_m )
  51. {
  52. int r = ;
  53. int i ;
  54.  
  55. for ( i = ; i < n ; i ++ )
  56. if ( stu[i].mark > j_m )
  57. r ++ ;
  58.  
  59. return r ;
  60. }

  在此向librazy 和Matrix_R两位网友表示谢意。

高手看了,感觉惨不忍睹——关于“【ACM】杭电ACM题一直WA求高手看看代码”的更多相关文章

  1. 【ACM】杭电ACM题一直WA求高手看看代码

    数据测试了好几个都没问题,可以就是WA不让过,检测了2个小时还是没发现有什么问题T_T!!求高手看看代码,小弟在此谢谢各位哦! #include <stdio.h> #include &l ...

  2. 杭电acm阶段之理工大版

    想參加全国软件设计大赛C/C++语言组的同学,假设前一篇<C和指针课后练习题总结>没看完的,请先看完而且依照上面的训练做完,然后做以下的训练. 传送门:http://blog.csdn.n ...

  3. 杭电ACM题单

    杭电acm题目分类版本1 1002 简单的大数 1003 DP经典问题,最大连续子段和 1004 简单题 1005 找规律(循环点) 1006 感觉有点BT的题,我到现在还没过 1007 经典问题,最 ...

  4. 杭电acm 1040题

    本题是一个非常简单的升序排序题目,但那时在做的时候把题目看错了,导致花费了大量的时间来检查为什么WA,最后发现题目看错了..... /********************************* ...

  5. 杭电acm 1022题

    Problem Description As the new term comes, the Ignatius Train Station is very busy nowadays. A lot o ...

  6. 杭电acm刷题顺序

    最近兴趣来了,闲暇之余,回顾大学期间刷过的杭电acm那些入门级别的题,以此巩固基础知识! 以下参考刷题顺序,避免入坑 原文传送门:https://blog.csdn.net/liuqiyao_01/a ...

  7. 杭电ACM分类

    杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze ...

  8. 杭电ACM(1002) -- A + B Problem II 大数相加 -提交通过

    杭电ACM(1002)大数相加 A + B Problem II Problem DescriptionI have a very simple problem for you. Given two ...

  9. 杭电acm习题分类

    专注于C语言编程 C Programming Practice Problems (Programming Challenges) 杭电ACM题目分类 基础题:1000.1001.1004.1005. ...

随机推荐

  1. Fiddler-008-简单模拟性能测试

    通过 Fiddler 可以简单的模拟性能测试的并发测试,此方法非常的简单,直接讲述如何使用,敬请参阅! 首先我们要获取需要并发的 HTTP请求,此操作非常简单,则在此不再赘述.获取到响应的 HTTP请 ...

  2. C#中jQuery Ajax实例(一)

    目标:在aspx页面输入两参数,传到后台.cs代码,在无刷新显示到前台 下面是我的Ajax异步传值的第一个实例 1.前台html代码: <html xmlns="http://www. ...

  3. 在Fedora8上的Tomcat上deploy一个war

    成龙有个电影叫简单任务,下面要讲的也是简单任务--具体来说是把一个war发布到在Fedora8上的tomcat6上. 在发布之前,需要先配置一个manager角色的任务,否则点Tomcat manna ...

  4. docker:从 tomcat 容器连接到 mysql 容器

    docker 中的容器互联是一个较为复杂的话题,详细内容将在后续章节中介绍. 续前 2 个章节的内容,我们创建了一个 mysql 容器和一个 tomcat 容器,可以使用 「docker ps」来查看 ...

  5. Android RecycleView + CardView 控件简析

    今天使用了V7包加入的RecycleView 和 CardView,写篇简析. 先上效果图: 原理图: 这是RecycleView的工作原理: 1.LayoutManager用来处理RecycleVi ...

  6. Windows 下用 gogs 配置局域网 git server

    大道曙光 Windows 下用 gogs 配置局域网 git server 最近要用 C# 开发一个新的项目,所以需要在 Windows 局域网环境下构建一个 git server. 在 Window ...

  7. T4教程1 T4模版引擎之基础入门

    T4模版引擎之基础入门   额,T4好陌生的名字,和NuGet一样很悲催,不为世人所熟知,却又在背后默默无闻的奉献着,直到现在我们项目组的人除了我之外,其它人还是对其豪无兴趣,基本上是连看一眼都懒得看 ...

  8. Google File System翻译(转)

    摘要 我们设计实现了google文件系统,一个面向大规模分布式数据密集性应用的可扩展分布式文件系统.它运行在廉价的商品化硬件上提供容错功能,为大量的客户端提供高的整体性能. 尽管与现有的分布式文件系统 ...

  9. 如何查看lib文件的导出函数

    参考:http://blog.csdn.net/brioxu/article/details/6932350 dumpbin /exports /out:xxx.dmp xxx.lib

  10. Swing 顶层容器

    顶层容器值得是容纳其他容器的容器组件,包括JFrame类,JWindows类,JDialog类,JApplet等.Swing中的顶层容器类Swing提供三个顶层容器类:JFrame,JDialog和J ...