ACM算法竞赛入门 概述

文章目录

  • 扩展:算法竞赛-培养杰出程序员的捷径
  • 算法竞赛入门
    • 1. 竞赛语言和训练平台
    • 2. 判题和基本的输入输出
    • 3. 测试
    • 4. 编码速度:唯快不破!
    • 5. 模板
    • 6. 题目分类
    • 7. 代码规范

扩展:算法竞赛-培养杰出程序员的捷径

  • 杰出的程序员往往具备:
    1. 掌握多种编程语言
    2. 代码量大
    3. 算法知识丰富
    4. 数学强
    5. 做过很多项目
    6. 有团队精神
    7. 有创新意识
    8. 会选择行业方向
    9. etc…

  比尔·盖茨曾说过:“如果你想雇用一个工程师,看看他写的代码就够了。如果他没写过大量代码,就不要雇用他。”通过编写大量代码,能做到算法精妙合理、逻辑清晰透彻、代码喷涌而出、格式赏心悦目、挑 bug手到擒来,这是杰出程序员的基本功。ACM-ICPC 竞赛队员想达到在区域赛中获奖的水平,需要写5~10万行的代码。

算法竞赛入门

  ACM-ICPC(Association for Computing Machinery-International Collegiate Programming Contest): ACM国际大学生程序设计竞赛

1. 竞赛语言和训练平台

  • 代理网站 列出了著名OJ
    ACM算法竞赛入门 概述_第1张图片

  • NOI的OJ:高中NOI信息学竞赛
    CCF的OJ;洛谷
    大视野:网上简称bzoj

Notice:其中“洛谷试炼场”题目分类比较全,是很好的基础学习平台。

2. 判题和基本的输入输出

  • OJ的判题
  1. OJ由机器自动判题,但机器并没有看懂代码的智能;即使是人工判题,人也很难短时间看懂程序。

  2. OJ判题是一种黑盒测试,它并不关心程序的内容,而是用测试数据来验证。

  • OJ的判题结果
    在这里插入图片描述
  • 打表
  1. 由于OJ不看程序内容,只关心程序的输入和输出,因此,在程序中不写详细过程,而是用printf或cout直接打印结果,也是允许的,这种方法叫“打表”。
  2. 另外,程序可能需要预处理数据,这个做法也称为“打表”。
  • 输入输出函数
  1. C++:输入函数cin,输出函数cout。

  2. C语言:输入函数scanf,输出函数printf。

  • 标准输入输出
    Description:OJ默认使用stdin和stdout,所以在提交程序时,并不用管OJ是怎么进行数据测试的。
    Notice:如果用到其它方法,会特别说明。
    提交过程图
  • 输入的结束-多组输入(以C语言为例)
  1. 默认结束(结束条件为无内容输入)

    int main(void){
           
    	int a, b;       // 输入a、b
    	while (scanf("%d %d", &a, &b) != EOF){
             // EOF: 文件结束符(end-of-file)
        // 等价于while (~scanf("%d %d", &a, &b)){  // scanf函数读取不到数据后,会返回EOF,这是在stdio.h里面定义的常量(通常值为-1),表示输入流已经结束,-1在计算机里用二进制表达就是全1,“~”代表逻辑运算按位取反
      		// ...... ;  
    	}
    	return 0;
    }
    // 推荐用 while (~scanf("%d %d", &a, &b))
    
  2. 在输入数据中指定数据个数
    eg:hdu 1090题

    int main(){
           
    	    int n, a, b; 
    	    scanf("%d", &n);   
    	    while (n--){
           
        			scanf("%d %d", &a, &b);
     			printf("%d\n", a + b);
       	    } 
    	    return 0;
    	}
    
  3. 以特定元素作为结束符。
    eg:以0作为结束符,输入读到0时,就退出:

    while(~scanf("%d", &n) && n);
    
  • 输入输出的效率

cin和cout效率低:与scanf、printf相比,cin、cout的效率很低,速度很慢。

如果题目中有大量测试数据,由于cin、cout输入输出慢,可能导致TLE。在这种情况下,应使用scanf、printf。

3. 测试

Explain:一个队伍中,安排一个队员负责构造测试数据。
把构造出的输入数据放在文件test.in里,程序的结果输出到文件test.out里。

输出文件test.out可以不要:直接在屏幕上看输出结果。
Notice:c++中创建.in文件,c++调用.in文件

  • 测试的两种方法:
  1. 在程序中加入测试代码

    #define mytest  // 定义一个预处理宏
    #ifdef  mytest  // 判断某个宏是否被定义,若已定义,执行随后的语句
    	freopen(“test.in”, “r”, stdin);  // 读数据文件标准输入
     	freopen(“test.out”, “w”, stdout);  // 将结果标准写入到输出文件
    #endif  // #if, #ifdef, #ifndef这些条件命令的结束标志
    
  2. 在行命令中重定向

Description:不用在程序中加任何代码。例如生成的的可执行程序是abc,在windows或linux的行命令中,这样输入和输出到文件:

abc .in >test.out
  • 对比测试数据
      复杂的题目,需要测试情况很多。可写两个程序,进行“对拍”。测试的时候,比较两个程序的输出是否一致。
    1. 提交到OJ的“好”程序;

    2. 暴力法程序,目的是用它生成测试数据 。

    3. 例如在windows系统下,生成的可执行文件分别是abc.exe、abc_1.exe,用文件比较命令fc比较它们的输出是否一致。

      abc.exe <test.in >test1.out
      abc_1.exe <test.in >test2.out
      fc test1.out test2.out /n
      
    4. 在linux系统中,文件比较命令是diff

4. 编码速度:唯快不破!

  1. 读题要快
  2. 熟练掌握编辑器或IDE
  3. 不要“霸占”计算机
  4. 减少调试
  5. 互相检查
  6. 使用STL
  • 减少调试
    1. 机时非常宝贵,除了必要的代码输入和测试外,尽量少使用计算机,把机时让给队友。
    2. 为了减少调试,尽量使用不容易出错的方法,例如少用指针、使用静态数组、把逻辑功能模块化等等。
    3. 不要使用动态调试、单步跟踪、断点等调试工具。如果需要查看中间数据,就用cout或printf打印出调试信息。
    4. 程序如果有问题,不要在电脑上检查,应该打印出来坐在旁边看,把机时让给队友。

5. 模板

  • 神器:模板
    1. 模板题并不常见
    2. 抄模板的能力
    3. 综合模板的能力
    4. 建模能力

6. 题目分类

  • ACM题目分类–大类
    Ad Hoc,杂题
    Complete Search (Iterative/Recursive) ,穷举搜索(迭代/回溯)
    Divide and Conquer,分治法
    Greedy (usually the original ones),贪心法
    Dynamic Programming (usually the original ones),动态规划
    Graph,图论
    Mathematics,数学
    String Processing,模式匹配
    Computational Geometry,计算几何
    Some Harder/Rare Problems,罕见问题

    杂题可能很难:
    有些题只考察逻辑能力和编码能力,并不涉及数据结构或算法下面的题目都是大型模拟题,以繁琐、坑人而著名:

    1. Bzoj 1972,猪国杀;
    2. Bzoj 1033,杀蚂蚁;
    3. Bzoj 2548,灭鼠行动。
  • ACM的知识宝库–细分

    1. ACM 中常用的算法
    2. ACM编程进阶
    3. IOI(The International Olympiad in Informatics Syllabus)大纲
    4. OI省选算法汇总

7. 代码规范

  • Google C++规范
  • Linux C规范
  1. 使用万能头文件 #include ,OJ网站一般都支持,只有poj不支持。

  2. 输入判断结尾不要用EOF,用 ‘~’,例如:

    ~scanf("%d", &n)
    
  3. 换行。用 K&R 风格,即左大括号不换行,右大括号单列一行。

  4. 变量定义。变量定义在这个变量被调用的最近的地方,例如:

    for (int i = 0; i < 10; i++)       //i只在这个循环体内使用
     		int s = i * i;
    
  5. 最好不要用宏。不管是宏定义,还是宏函数,都容易出问题。不要用#define定义常量,而是用const定义常量,例如:
    const int MAX = 1000005;把宏函数写成普通函数。

你可能感兴趣的:(ACM,算法分析与设计,c++,c语言,算法,acm竞赛,程序设计)