每年 CSP-J/S 复赛都有很多同学因为一些小失误导致一年的努力付之东流。Tony老师整理了一些复赛容易踩坑的点,或许对你有帮助!
一、文件的输入输出
CSP、NOIP复赛与我们平时在Online Judge做题形式会有一些区别,需要我们将文件放入规定的地点,然后提交汇总,系统判题以后才能得到分数。
其中,每道题都有一个自己的源文件名,比如:aiport.cpp , bracket.cpp , palin.cpp , traffic.cpp,我们同学需要进行如下操作:
1. 打开文件
2. 对文件进行读写操作
3. 关闭文件(可省略不写)
这边帮助大家总结了简单步骤,大家只需要跟着操作就ok啦!
1. 头文件必须包含:#include<cstdio>
2. 在主函数的开头写两句话:
(1) freopen("XXXX.in", "r", stdin) ;
(2) freopen("XXXX.out", "w", stdout) ;
上面的XXXX.in和XXXX.out就是对应着题目的输入文件名和输出文件名,例如freopen("airport.in", "r", stdin) ;
3. 在主函数末尾写两句话:
(1) fclose(stdin);
(2) fclose(stdout);
其中第三步是关闭文件,可以省略不写。
完整的代码模板如下:
#include <cstdio>
#include <iostream>
using namespace std;
int main(){
//打开对应的输入数据文件和输出数据文件
freopen("XXXX.in", "r", stdin);
freopen("XXXX.out", "w", stdout);
//原来代码保持不变
printf("祝大家统统满分!");
//关闭文件,可省略
fclose(stdin);
fclose(stdout);
return 0;
}
但是要注意,当加了freopen两句话以后,就没有办法像之前那样测试数据了,所以建议大家在写完这两句话以后先注释掉,等程序测试无误以后再去掉注释。一定要记得去掉注释!!!
最后再提醒一下!
二、注意文件名字
文件夹名、程序文件名、输入文件名、输出文件名
每道题这部分的英文名称都是一样的,都是小写,一定要多检查几遍!
三、注输出格式和大小写问题
1. 注意题目要求输出的多行数据,是否需要换行、是否需要空格以及对应空格的数量
2. 注意输出yes、no、right、impossible等英文提示时,是否要求首字母大写,大小写在Linux下面是不一样的。
四、注意定时保存文件
为了防止突发事件,至少20分钟存盘一次。千万不要关机,否则程序会丢失。
五、注意头文件及命名空间
头文件太多时,容易忘写using namespace std;
但是用了using namespace std; 之后容易产生的问题是:自己的变量名和std命名空间的变量名冲突,而且在Windows下编译器不报错,在Linux下报错。所以自己的变量名不要使用hash、x0、x1、y0、y1,time、next、pipe等。
如果需要这几个单词,可以用Time、Next等个字母大写或者加上一些字母,如mytime、mynext等,或者定义成局部变量。
六、注意变量初始化
变量、数组在使用之前忘了初始化,里面的值是随机的,结果就会出问题,所以使用的时候不要忘记初始化,可以定义成全局变量,系统会自动初始化。
七、数据类型
注意数据类型,输入输出的时候占位符和数据类型要一致,不一致在有时候可能结果也没有错误,但是评测的时候可能就有问题,比如long long的数据类型不能用“%d”,而应该用“%lld”。
八、注意字符串读入方式
由于gets函数会造成安全隐患,在C++中已经被弃用,所以注意不要使用gets函数。可以使用:fgets\getchar\scanf\std::cin或其他读入方式。
九、数组
C++里数组有时候可能会出现莫名其妙的问题,所以一定要记得把数组开大点,并且赋初值。
最好是开成全局变量,因为在main函数里定义的是局部变量,给你的空间会比较小,二维数组很容易就爆了。
还有要注意千万不要数组越界,以下用代码说明:
//比如题目要求n个数, n的范围为0 <= n <= 10000, 很多同学喜欢用下面的方式
int n;
cin >> n;
int a[n+5];
但这是一个错误的定义方式,直接会导致数组越界。因为在编译阶段就会开辟数组的空间,然而在这个时候n并没有输入值,所以会导致n的值随机,开辟一个随机的大小,很容易导致数组越界。
以下是正确的定义方式:
//0 <= n <= 10000
const int N = 1e4 + 5;
int a[N]
//或者
int a[10005];
十、时间空间资源和精度
1000毫秒内较大循环次数不要超过10^8(10^8有点悬,10^7不超时)。
空间限制在128MB时,数组元素类型为int时,元素个数较多别(约3*10^7),要定义在到main函数外面的全局变量区(二维数组的两个维度大小要相乘)。
十一、数据范围
有的题目,多个数相加,每个数的较大值就到了1e9,那么存放和的变量就必须是long long。有的题目,边权的较大值都到了1e9,并且更新较短路径时两个边权相加,结果就是2e9。
那么我们在为数组元素赋值为无穷大时,应该设多少呢?
我们的无穷大可以是1e9+1,或者0x3f3f3f3f =十进制1061109567
0x7f7f7f7f = 十进制2139062143
int的范围是 - 2147483648 ~ 2147483647 。
所以程序中的无穷大可以定义为1e9+1或0x3f3f3f3f。
十二、注意图的建立
建立图的邻接矩阵和邻接表时,注意单向边和双向边,重边,自环等情况。
十三、上机操作 文件的建立
首先考试时需要从局域网里下载题目和样例数据(下载之后可能需要解压缩),这是第一个文件夹,这个文件夹可随意命名,比如“题目”或“Problem”,或者按默认的名字。提交题目时需要在桌面建立以准考证号命名的文件夹(比如BJ-001),这是第二个文件夹。另外有些选手不想把自己的cpp程序和in文件、out文件放在第一个或第二个文件夹里,这时可以创建第三个文件夹,这个文件夹可以随意命名,比如MyCode。这三个文件夹如下图所示。
MyCode文件夹里面可以再为每道题创建一个子文件夹,也可以不建立,这个无所谓,反正这个文件夹不用上交。假如不为每道题创建子文件夹的话,那么以CSP-J2019复赛为例,目录结构如下图所示:
注意:
(1)上图是假定四题都做的情况。如果有题目不会做,就不需要有相应的cpp文件和in、out文件。
(2)每个程序里要加文件输入输出代码,比如
freopen(“number.in”, “r”, stdin);
freopen(“number.out”, “w”, stout);
注意,noilinux下使用freopen,需要包含头文件stdio.h或cstdio或直接使用万能头文件bits/stdc++.h。
(3)xxx.cpp文件需要手动创建。后缀名.cpp在noilinux下需要自己手动填写,无论用gedit还是用emacs还是用guide软件都不会自动生成后缀名,网络上有文章说后缀名会自动生成,这是个误导。
(4)xxx.in文件可以手动文件,也可以把Problem文件夹下面的测试数据比如number1.in或number2.in拷贝到MyCode下,然后重命名把数字编号去掉,即把number1.in或number2.in改成number.in。
(5)xxx.out文件一定不要手动创建,成功运行程序后会自动生成.out文件。如果没生成.out文件即表示程序有误,应检查两行freopen代码尤其是第二行。
(6)题目里会有number1.out或number1.ans或number2.out或number2.ans之类的文件,这个是用来与你的程序生成的number.out中的答案相对照从而判断你的运行结果是否正确。number.out中的运行结果也可以与卷子里的样例结果相对照。
(7)xxx.cpp这里的文件名和freopen中的第一个参数的文件名、xxx.in、xxx.out文件的名称都是一样的,若不一样,肯定有错。比如程序名是number.cpp,那么两行freopen代码的第一个参数如第(2)条所示,所创建的输入文件名为number.in,程序生成的输出文件名为number.out。
(8)最后提交程序时,只需要提交.cpp文件,不需要提交.in和.out文件。
提交的文件夹目录结构如下图所示:
注意:
(1)上图假定四题都会做。如果只会做三题,那么另一题可以不建立题目文件夹和.cpp文件。