OI比赛注意

来源:互联网 发布:阿里云分布式文件系统 编辑:程序博客网 时间:2024/05/01 03:02
             这篇东西将永远置顶到我的OI生涯结束,我也会根据实际情况而做修改,希望也能帮助到其他的OIER。

一、竞赛过程
step1:审题(30分钟左右)
1、通读题目
2、对问题在算法层次思考(注意不要漏掉题目中任何条件)
3、估量题目实现难度(算法设计难度、编程复杂度)
4、按照实现难度从小到大制定做题顺序
先做把握大的题,什么是把握大的题?也就是思路完整,算法熟悉,易于调试的题。

(虽然题时由简单到难,但还是先读一遍较好,这样心里有底,才可以合理分配时间)

step2:构思、编写代码
1、设计算法、存储结构(程序模块)
2、验证算法(证明或找反例)
3、编写代码(对模块细化)
编码细心与否,直接决定了下一步也就是调试的难度。看着自己在纸上写出的程序框架(一定要有,很重要,可以帮你节约不少时间),小心地把代码写出来,参数尽量使用有意义的名称。 (变量的初始化一定要注意啊啊啊!)
这一步不求快,但求稳,一定不要犯低级错误。写完整个程序后不要急于编译,先把程序通读一遍(这一步有很多人都忽略掉,最好不要忽略,很有帮助的),确认无误后再开始编译调试。

step3:测试、调试
1、设计数据,黑盒测试(数据要全面:划分等价类,每一类取典型小规模数据;设计边界数据;
数组常数设小点,测试数组越界,但别忘了改回来;有规律大数据测试时空承受能力)
2、调试
模块化调试,先跳过过程函数看结果是否正确,若不正确锁定出错模块集中调试
3、静态检查排错

step4:检查
1、程序名、大小写
2、文件输入输出
3、数组范围常量改回来没有,其他常量改了吗

二、关于骗分
方法0、简单贪心

方法1、输出特定条件的解
有时候一个问题条件复杂,我们想不出很好的解法,但是简化了某些条件以后,解很容易求出。
这样的题目,我们可以找到条件,使用多个if语句,根据简化条件输出问题的解。
这样的方法往往比简单贪心好些。

方法2、小规模数据搜索、大规模数据贪心
例如
readln(n);
if n<100 then
搜索
else
贪心

方法3、搜索+贪心
如果问题要求最优解,宽搜的时候可以对于给一步选择设个估价函数,
只保留估价函数最优的几个进队;深搜时可以设置一个阀值,超过该阀值
的就不进行搜索。
关键问题有2点:
1、估价函数、阀值如何定
估价函数通常是代表走向最优解的可能性,例如“传染病控制”一题中
我们只需要枚举孩子结点个数最小的前5个即可,这里孩子结点个数就是
估价函数。
2、深搜的阀值要由经验和试验得出,可以程序产生大规模数据试验阀值

三、赛前时间利用
竞赛开始前一段时间,编写快排、最短路径(dijkstra和floyd)算法
竞赛开始之前约30分钟时间内,快速编出快排、最短路径模块。即能够
快速进入比赛状态、又能够使用这些模块解题,达到节省比赛时间的效果。

(有助于节约时间,时间很重要)

四、输出格式
逐字节比较,一行如果有多个数时最后不要多加空格,如果输出最后一行,
语句应是writeln(...)

附:   比赛技巧

关于调试和测试:
1.下面是几种比较常见的错误:
1.输入输出格式错误
2.数据类型错误(尽量用大的类型)
3.范围检查错误(可以稍稍加大上下界)
4.变量名称错误
5.漏语句(看事先设计好的变量是否都用上了,然后看每个模块是否实现了应有的功能,是否完成了接口)
2.我们应对于每道题设计充分的测试数据,并保留那些比较具有代表性的测试数据,以便于优化的时候比对.
3.一定要记住删除屏幕输出!
4.最后一定要记住关闭程序中用于临时调试的特殊设置和语句!
5.输出数据的每一行(包括最后一行)必须以一个换行符结束,行末不要保留多余空格。对于每一道试题,在相应的目录中都有一个格式检查程序来检查输出文件格式的合法性。该程序的文件名是:<shortname>_check。格式检查程序仅仅检查输出文件名的正确性和文件格式的合法性而不检查结果的正确性。检查结果显示在屏幕上。
6.如果领队或参赛选手对评测结果有异议,可以填写相应的表格,并在评测结果公布后的三个小时之内提交评测委员会申请复议或复评。当领队或参赛选手对复议或复评结果仍有异议时,应提交NOI科学委员会仲裁,并以NOI科学委员会的仲裁结果为该项评测的最终结果。
7.调试的时候,一定要钻输入文件的牛角尖,考虑到各种情况。
8.调试的时候,常常可以编一个非常非常易编的程序,采用算两次的方法,不过前提是必须保证正确。
9.Writeln是Fp中最笨但又是最准确的调试方法。
10.调试时每发现一个错误,都最好浏览一下整个程序,看是否有类似错误,这样非常有效!
11.在每一处可以中止程序的地方,都要看一看是否需要close file.
12.程序出现不确定性的问题,如对于同样数据,有时死机,有时不死机,但多半都是随机模块有误!
13.指针出错常常是出现了Nil^.Next
14.递归程序的调试应该使用F7(F8)+Call Stack,尽量不要用F4。
15.不要只顾埋头拉车,要抬头看路。当被一两个子程莫名其妙的错误弄得晕头转向的时候,记住:很可能错误在其他地方。
16.读写文件之前才打开文件,操作完毕立即关闭。
17.每改完一个错误要想想是否改正确了,是否改彻底了,程序中(特别是有Paste的地方)是否有相同错误。
18.很多题目最易忽视的就是初状态=末状态的情况,还有初状态和末状态存在可操作的决策。(如Mars Explorer)
19.多考虑一些特例,在这方面认真些,全面些,仔细些,常比多考虑些时空上限划算得多。
20.编函数的时候千万别忘了给函数赋返回值,否则会引起随机性错误。
21.调试语句一般和上下文保留一空行,最好加上注释,并且一定记住在最后删除。
22.中途输出后结束一定要记住Halt
23.Byte,Shortint调试会以String类型出现,第一位以字符串长处理,遇到#0中止。FP和RHIDE中皆如此。
24.FP中的Extended类型有时候变量值未改变。
25.调试和测试的时候一定要充分考虑到各种边界和特殊情况。
26.自测时千万不要忘测数据上限,主要是看是否会超界。大半错误均源于此!之后仔细察看Const中的数。
27.大数组处理很容易出错,所以尽量避免开过大的数组及其调试。
28.多维数组的调试RHIDE比FP Bug还多,而大数组多元素的查看可考虑使用RHIDE
关于算法
1.关于复杂度涉及logN的算法.logN常常是因为二分,树,Heap,排序等造成的,而且有一点应该注意到,logN更接近一个常数,而不是N.
2.涉及矩阵的统计问题,通常而言,降维策略是非常有效的,而且常常是在外层枚举用土方法,内层枚举使用优化过的方法。另外,用O(N*N)枚举出Y1,Y2,然后考察之间夹的矩形是非常常用的方法。
3.涉及01串的问题,都不要忘记位运算和压缩,同时也要小心。
4.对于判重问题,关注最小表示。
5.有序化的处理常常比无序的简单,所以,对于想不出算法的题目,先有序化!
6.对于涉及子序列之和的问题,如NOI Sequence ,CEOI Parity,B&W,常常化为第一位到某一位的和。
7.大数据量的题目,有时候分多次读入数据会非常有效
8.对于一边明显长于另外一边的矩形问题,常常是基于短边的指数化或者是阶乘算法,而基于长边的O(N)或者O(N*N)的算法。
9.我们应该注意,许多求割点的题目是求给定两点间的割点,而不是普遍意义上的割点。
10.没有回溯的搜索是最成功的搜索。
11.如果你的算法在最大规模的时候要爆,但是最大规模的数据非常难设计,那么就不要管他,设计一个稍次一点的算法就行了。
12.尽量让程序不做已做过的事和显然没有必要的事,也不要解决无用的子问题和对结果进行无意义的引用。
13.A*算法的估价函数一般而言要保守些,不要为了速度的一点提升丢失了最优解。
14.一般情况下,根据数据规模猜算法是非常有效的。
15.聚焦边界!
16.对于流量不超过给定值的最大流问题,注意取流值的时候。
17.Qsort算法要注意应该先存储选为基点的那个数以后再比较,比较函数一定要保证Compare(A,A)=False!
18.我们不仅关心算法的时间复杂度,还要关注最内层的循环到底在干什么。
19.在只涉及乘除的高精度运算中,按因数存储的效率远高于按位存储的效率。
20.动态规划和递推更多应考虑本问题由哪些已解决子问题构成,而不是考虑本问题对将来哪些问题有贡献。
21.深度优先搜索候(如求割顶、桥、强连通分支),一定要记住常常题中不止一棵搜索树,也常常有重边!
22.优化的时候不要去考虑最坏的情况下是否有太大的意义,只要在大多数情况下有比较明显的作用就行。
23.对于大规模的Dijkstra算法,如果数据不容易出得很刁的话,用迭代代替堆也是不错的选择。用可更新队列实现也不错。
24.很多图论模型中都要考虑到重边,即使是自己建的图中也有可能出现重边(Knights)。
25.很多情况下,“不超前”属性的引入可以使复杂度降低一个数量级。
26.很多时候,由于DP空间开销很大,我们只能保留一个阶段,这时候从大到小的规划时常收效颇佳。
27.对于数学味较浓的问题,变量的取值范围与计算公式同等重要。
28.博弈问题从残局或结局出发分析往往会有惊人的发现。
29.博弈问题胜负局面的相加运算符合Xor(也就是和mod 2)
关于数据结构
1.涉及单词的问题,常常因为单词的数目多,而且长短不一,出现存储问题,我们可以读入整个数据文件,然后对每个单词记录起止点,这样就充分利用了空间。
2.事实上,链表的速度并不比有序数组高多少,虽然具有O(1)的插入删除复杂度,但是他的查找是O(N)的,而有序数组虽然插入删除是O(N)的,但是查找是O(logN)的。而且后者好编些。
3.多用Longint,少用Integer,反正闲着也是闲着。
4.传统数据结构的创新性珠联璧合是现代数据结构试题的发展方向。比如邻接矩阵+邻接链表。
5.Joseph类问题中,如果采用静态数组,删除节点可能导致指针错误。
6.并查集Combine时切记看两个Fa是否相同,否则可能引入圈。
7.Bignum有时应注意[0]不止256位
8.有时候,将链表和数组珠联璧合,如在大规模约瑟夫环中,会受到很好的效果。
9.在处理小规模链表的问题中,采用静态指针(数组)效果比较理想,便于调试。(比如多维背包)
todo
关于FP及程序实现
1.有时候要有意采用ln,exp变*为+
2.有时与其追求非常精炼代码,还不如笨拙的枚举各种情况,只是注意在Copy&Paste的时候不要出错。
3.涉及坐标的问题,常常要考虑坐标的定义是基于最小区间的还是基于点的。
4.Linux中虽然FP IDE中Ctrl失效,但执行程序的时候,Ctrl+Pause或者Ctrl+Z(C)是可以用的
5.对于涉及时间的问题,我们必须注意题目中所说的时间是指时间段还是指时间点。
6.凡是分母为变量的除法、Div、Mod都需要想一想是否要判0
7.永远不要忘记在程序调试完以后改大Const!
8.双向搜索与其在精炼的代码上挣扎,还不如就两边分别写过程,只是注意不要乱Copy&Paste.
9.链表的实现常常可以采用虚节点的方法,但不要生搬硬套,有时候采用虚节点不一定更好.
10.非等差循环用while不用for.
11.实数运算永远记住用Zero!(要除了计算几何的一些经典算法,如Graham)。
12.Gcd,路经压缩,二分查找等很短的递归最好化为非递归形式
13.记住,测试数据只是用来发现错误,而不是用来改正错误的,依靠测试数据改正错误,越改越糊涂!
14.注意计算几何中Infinite的引入。
15.很多时候,输入的两个数据并没有说明两者的大小关系!
16.注意FillWord和FillDWord分别是Div2,Div4,而后者类型为Dword,可正可负。
17.枚举的时候不要忘记想一想是用To还是Downto更好。
18.编写DFS之前一定要先考虑最坏的情况下栈空间是否够用。
19.Int64不能用Read,也不能直接赋给一个大于Longint的值。
20.Gcd中,我们不用if a mod b=0 then gcd:=b else gcd:=gcd(b,a mod b),而用if b=0 then gcd:=a else gcd:=(b,a mod b),因为前者用了两个Mod.
21.Gcd,Mod,Div的使用都应该注意正负。
22.交互问题一定要注意接口。
23.开大数组相当花时间。
24.A mod 8=A and 7
25.编之前应该想好需要变的子程,不要做无用功,同时也为反复调用提供思路。
26.重要结论:a,b取值为{0,1},则a xor b=(a+b) mod 2
27.FP中不要使用集合
28.对于取余输出,我们用(a-b+c) mod c而不是(a-b) mod c
29.一定不要忘记初始化。
30.在很多情况下,Xor运算可以使代码更简洁高效。
其它
1.在竞赛开始的一个小时之内,参赛选手可以就试题中模糊不清的内容提出疑问。提问应使用专用表格,一题一表。回答内容应是“是”、“否”、或“无可奉告”。等待答案的时间计算在选手竞赛时间之内。
2.在竞赛期间,参赛选手应及时将自己的文件备份,以便当出现设备故障时迅速恢复文件。文件备份应放在/tmp目录之下。
3.理解题意的时候千万不要想当然,只去做题目说的东西,不要假设任何题目没有提及到的条件。
4.表达式处理中注意形如(a+b)*(c+d)的括号。
5.有少数题目不是按照先行后列的方式组织数据的,这一点要格外注意。
6.记住:非明文禁止者,皆不无可能。
7.比赛不要轻易删文件,尤其不要加通配符。
8.文件名切记要使用小写!
9.Settextbuf在Linux下面同样有用。
10.要小心,10^8有9位,不是8位。9E14是指9*10^14,不是 9^14 !
11.Waste memory when it makes your life easier .
12.Keep all working versions!
13.USE Precomputation !
14.Pay attention to Symmetries!
常见运行错误
002 文件未找到           005 文件不允许访问          102-105 (检查assign,reset,rewrite)
106 无效数值格式    200 被零除           201 范围检查错
202 栈溢出      203 堆溢出        204 无效的指针操作 205 浮点运算上溢 206 浮点运算下溢     207 无效浮点运算215算术运算上溢216 一般保护性错误

原创粉丝点击