按  

  被中科大软件学院二年级研究生 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求高手看看代码

原代码:

#include <stdio.h>
#include <stdlib.h>
#define max 1000
/* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char *argv[]) {
int stu[max]; //学生的ID
int stur[max]; //学生的成绩
int rank,jack_id; //查找的ID
int flag[];
int i,jack,n;
freopen("in.txt","r",stdin);
while(scanf("%d",&jack)!=EOF){
for( i= ; i<max ;i++) {
stu[i]=;
stur[i]=;
}
for( i= ; i< ;i++) {
flag[i]=;
}
for( i= ; ;i++) {
scanf("%d%d",&stu[i],&stur[i]);
if(stu[i]==&&stur[i]==) break;
}
n=i;
for( i= ; i<n ; i++) {
if(jack==stu[i]) {
jack_id=i;
}
}
rank=;
for( i= ; i<n ; i++) {
if((stur[i]>stur[jack_id])&&(flag[stur[i]]!=)){ //找到比自己大的成绩rank++
rank++;
flag[stur[i]]=;
} }
printf("%d\n",rank); } return ;
}

评析:

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

#include <stdlib.h>

  不清楚做什么的,没用。

#define max 1000

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

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

  应该

int main( void ) {

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

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

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

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

    int flag[];        

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

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

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

        for( i= ; i<max ;i++) {
stu[i]=;
stur[i]=;
}

  这里写得很傻。其实只要

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

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

        for( i= ; i< ;i++) {
flag[i]=;
}

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

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

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

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

  下面给出我的写法:

重构:

#include <stdio.h>
#include <stdlib.h> typedef long num_t ;
#define FN "%ld"
typedef int mark_t ;
#define FM "%d" typedef
struct
{
num_t num ;
mark_t mark ;
}
STD; int input( STD [] , num_t , mark_t * );
int rank( STD [] , int , mark_t ); int main( void )
{
num_t jack_n ; while ( scanf( FN , &jack_n ) != EOF )
{
STD stu[ + ] ;
int sum ;
mark_t jack_m ; sum = input( stu , jack_n , &jack_m ); //输入并获得数据总数及Jack的成绩
printf("%d\n" , rank( stu , sum , jack_m ) );//输出Jack的名次
} system("PAUSE");
return ;
} int input( STD stu[] , num_t j_n , mark_t * p_j_m )
{
STD * p_ini = stu ; while ( scanf( FN FM , &stu->num , &stu->mark ) ,
stu->num != j_n ) //读入数据直到Jack的
stu ++ ; * p_j_m = stu++ -> mark ; while ( scanf( FN FM , &stu->num , &stu->mark ) ,
stu->num != || stu->mark != ) //读Jack后面的
stu ++ ; return stu - p_ini ;
} int rank( STD stu[] , int n , mark_t j_m )
{
int r = ;
int i ; for ( i = ; i < n ; i ++ )
if ( stu[i].mark > j_m )
r ++ ; return r ;
}

小结:

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

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

再次重构:

  根据 librazy 网友提供的信息:

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

  以及Matrix_R  网友的意见:

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

  再次重构代码如下:

 #include <stdio.h>
#include <stdlib.h> typedef
struct
{
int num ;
int mark ;
}
STD; int input( STD * , int , int * );
int rank( STD [] , int , int ); int main( void )
{
int jack_n ; while ( scanf( "%d" , &jack_n ) != EOF )
{
STD stu[ + ] ;
int sum ;
int jack_m ; sum = input( stu , jack_n , &jack_m ); //输入并获得数据总数及Jack的成绩
printf("%d\n" , rank( stu , sum , jack_m ) );//输出Jack的名次
} system("PAUSE");
return ;
} int input( STD * p_stu , int j_n , int * p_j_m )
{
STD * p_ini = p_stu ; while ( scanf( "%d%d" , &p_stu->num , &p_stu->mark ) ,
p_stu -> num != j_n ) //读入数据直到Jack的
p_stu ++ ; * p_j_m = p_stu ++ -> mark ; while ( scanf( "%d%d" , &p_stu->num , &p_stu->mark ) ,
p_stu->num != || p_stu->mark != ) //读Jack后面的
p_stu ++ ; return p_stu - p_ini ;
} int rank( STD stu[] , int n , int j_m )
{
int r = ;
int i ; for ( i = ; i < n ; i ++ )
if ( stu[i].mark > j_m )
r ++ ; return r ;
}

  在此向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. js判断input为空校验

    突然发现最近js发现的问题比较多,更发现我怎么快成了前端开发了?不能够啊!我后台怎么不出问题呢?我的后台是太简单了吗?mybatis-dao-service-controller返回给前台...... ...

  2. 10 Ways to Inspire Your Team

    Inspire. Just the word itself causes us to pause and think. We may remember our own personal heroes ...

  3. iOS面试题 02

    在面试的时候,面试官问我,“你对内存管理了解的多吗?” 我忘了当时是怎么回答的了,但是,肯定是一时没想起来怎么回答. 1.谁创建谁释放 2.autoreleasepool 3.retain,copy, ...

  4. Selenium2学习-016-WebUI自动化实战实例-014-Selenium 窗口选择

    在日常的 WebUI 自动化测试脚本编写过程中,经常需要打开新的页面,或者在多个打开的页面之间进行切换,以对页面元素进行相应的操作,以模拟用户的行为,实现 UI 的自动化测试.在过往的时间中,经常有初 ...

  5. c#上传文件(二)使用文件流保存文件

    1.html代码: <asp:FileUpload runat="server" ID="UpLoadFile"/> <asp:Button ...

  6. Keep Alive

    跳板机时经常出现连接被断开的情况.如果发生这种情况,请在客户端配置Keep Alive设置,具体方法参考如下: Windows: secureCRT:Properties -> Terminal ...

  7. [转载][MFC]MFC的美化

    转载:http://blog.csdn.net/b_silence/article/details/10489085 前些天用MFC开发一个桌面程序,实现功能后客户说界面太难看,自己仔细看看也着实难看 ...

  8. Date and Time Pattern

    The following examples show how date and time patterns are interpreted in the U.S. locale. The given ...

  9. 如何解决SQLServer占CPU100%

    文章目录 遇到的问题 使用SQLServer Profiler监控数据库 SQL1:查找最新的30条告警事件 SQL2:获取当前的总报警记录数 有哪些SQL语句会导致CPU过高? 查看SQL的查询计划 ...

  10. Spring Boot 5 SpringSecurity身份验证

    对于没有访问权限的用户需要转到登录表单页面.要实现访问控制的方法多种多样,可以通过Aop.拦截器实现,也可以通过框架实现(如:Apache Shiro.Spring Security). pom.xm ...