NOIP复习总结(搜索算法)

在这里插入图片描述
上图是一张时间复杂度对照表,考试的时候方便对照评价自己的算法是否会超时。仅供参考,还要考虑老年评测机的速度,算法常数等等……在这里插入图片描述
在这里插入图片描述
数据类型和占用空间对照

所以只用0,1表示的话还是开char好一些吧,在空间上来说在这里插入图片描述
int 类型和 long long 类型最多开到多少
加粗表示特别重要,必须掌握
倾斜表示最好掌握,可能性不是很大,但是某些可以提高程序效率

高精度
  a.加法
  b.减法
  c.乘法(应该只会有高精乘单精
  d.高精度除单精 (后面c,d考的可能性较小,应该只考a,b)

排序算法
  a.选择排序
  b.插入排序
  c.hash排序
  d.归并排序(单纯的排序可能用不到,有快排就行了,但是归并排序的思想很重要)
  e.堆排序
  f.快排

字符串匹配算法
  a.暴力法
  b.KMP(待学)

数论
  a**.欧几里德算法(用辗转相除法求最大公约数)**
  b.扩展欧几里德算法 ax+by=c 的正整数
  c.素数 O(sqrt(n))
  d.筛法求素数
  e.快速乘方(位运算+同余+高精)(矩阵加速也很可以的)

树论
  a.二叉搜索树
  b.优先队列(C++中priority_queue,相当于手动维护的小(大)根堆的数据结构优化)
  c.线段树 (RMQ问题建议使用st算法)
  d.平衡树一种(建议学习SBT)

图论
  a.拓扑排序
  b.割顶,割边(桥) {O(n)}
  c.强连通分支 O(n)
  d.有向无回路图的最长路径
  e.欧拉回路
  f.最小生成树
    ① Prime O(N2)
    ② Kruskal O(M2)

  g.次小生成树 {简单的删除最大边是不对的}
  h.最短路径
    ① Dijkstra
    ② Bellman-ford
    ③ spfa
    ④ flyod
    单源点最短路径算法推荐使用spfa(即使习惯dijkstra),Dijkstra不能有负边不能有回路,所以用spfa更保险(不过spfa现在很容易比卡也要看情况吧)

计算几何
  a.判断两条线段是否相交
  b.凸包算法 O(n)(待学)

其他算法
  a.并查集
  b.RMQ
  。。。。。。还有一些算法的思想性多于实操性就不写了
  NOIP临考经验

  1. 提前15分钟入场,此时静坐调整心态,适当的深呼吸

  2. 打开编辑器并调整为自己喜欢的界面

  3. 熟悉文件目录,写好准确无误的代码模板

  4. 压缩包或许还不能解压,但是文件名已经可以知道了,在选手目录下用代码模板建好所有文件,包 括.c/cpp/pas、.in、.out

  5. 开始比赛,不要急于看题目,将试题第一页的时间、内存限制等等一字不落地看完

  6. 看题目时不能走神,看完题目后将其归入某几个框架中,包括:模拟/枚举/搜索/贪心/动态规划/图论/分治

  7. 根据输入数据的范围大致确定算法复杂度,以下均是可能情况,不绝对:

    20:2^20=一百万,O(2^n),搜索
    
    100:100^3=一百万,O(n^3),Flody/APSP/搜索
    
    1000:1000^2=一百万,O(n^2),动态规划/图论
    
    500000:O(nlog(2,n)),二分答案/二分查找/快排/归并
    
    1000000:O(n)或O(1),数学问题/改变思维方向/贪心
    
  8. 写下代码前,必须保证有充足的思考时间,有成熟的想法后再动手

  9. 写代码前,尽量用多而强的数据去测试想到的算法,毕竟代码写完后再测试就浪费很多时间了

  10. 不能想一点写一点,就算是输入部分也要在整体思路理清后再写

  11. 永远别去写从未接触过的算法/数据结构

  12. 有多余时间一定要进行对拍,即3个程序:生成数据、朴素算法、准备交的算法

  13. 交之前5分钟千万不要再改动代码,主要留意代码中是否还有测试程序时留下的痕迹

  14. 走出考场后,除非已经是Day2,永远别对答案

现在特别想重点思考一下搜索算法
历届NOIP卡AK的方法除了树上题目与图论的巧用(暂时还没有外),就只有搜索是最大的利器了。多种需要考虑的状态,抛弃了DP灵巧的状态设计,注重贪心与模型转化类的剪枝(NOIP的剪枝往往缺失套路性,一题一类剪枝)。所以后期比赛想要在NOIP上拔得头筹必须稳住搜索。我们最先会的相对高级的算法就是搜索。

反观历年NOIP的搜索越来越难,什么最优性剪枝、搜索预处理……方法层出不穷。而应对的OIer也有许多令人诧异的发挥,例如充虫食算的高斯消元解法、愤怒的小鸟的FWT解法、华容道的A*写法、靶形数独的DLX……这些都是在利用高级算法解决爆搜就能解决的问题。所以NOIP的特点也就暴露无遗,可以用高级算法做,但不保证不卡时。在时间紧迫的情况下,有些同学会依仗自己学过的高级算法(数据结构学傻)无脑解,也有些同学好好分析完题目后巧妙地用基础算法解出。

不仅仅是搜索可以说CCF创建NOIP的目的就在此。

面对以上情况有两种解决方法:
1.学会较多的算法及其优化,就例如最短路的三种写法,及其不同的优化,应用的数据特点……即使不是正解会被卡20左右的数据,也不会影响你的分数
实现方式:等同于随机做题数量260+(除开水题)

2.培养强大的模型转化能力,在NOIP的考场上,绝大多数题目不会是代码量巨大的数据结构或图论题,即使是搜索题,养成良好习惯,代码行数也不会太多。依靠比赛经验,你可以快速把一道题类化成其他题目,灵活地运用题目性质快速且准确的解决题目。

上述两种方法各有优劣:
第一种没办法解决题目信息奇怪,自己无法理解(NOIP应该不会出现)或者不好套用算法的题目,第二种无法解决考点就是自己没有学过的知识的题目。
相比之下(我不会说什么都要会,这对于大多数NOIP级别的OIer太苛刻了),选择第二种是更好的。

NOIP的题目除开送分题,以拿NOIP一等的条件就是搜索功底扎实。写搜索时放开心扉,不要去一个劲的在意复杂度,先以指数级别的算法学出来再考虑优化。对于这类的搜索题,正解不是(对于大多数NOIP级别OIer来说)一蹴而就的,往往需要经过许多的调试与优化。调试我就不说了(除非你会gdb最好别用调试,太花时间了,中间过程输出真的好,有助你培养一个更加严密的逻辑思维。),优化就各凭本事了,什么能加的都加上也不说了(这些都是作为老选手的经验),那么决胜的还是你是否能够写得出正解啊!!

繁琐的搜索,考的就是耐心与细心,NOIP不是省选,不会看不起写暴力的人(至少从往届来看暴力分给得很足),那么有一个60%正确的正解与90%正确的70暴力放在我眼前时,我会毫不犹豫地选择后者,因为NOIP最后比的是分数,暴力分少但稳定,可以防爆啊。

/
/
/
/

第一部分 基本的搜索算法
一、回溯算法
回溯算法是所有搜索算法中最为基本的一种算法,其采用了一种“走不通就掉头”思想作为其控制结构,其相当于采用了先根遍历的方法来构造解答树,可用于找解或所有解以及最优解。

评价:回溯算法对空间的消耗较少,当其与分枝定界法一起使用时,对于所求解在解答树中层较深的问题 有较好的效果。但应避免在后继节点可能与前继节点相同的问题中使用,以免产生循环。
/
/
二、深度搜索与广度搜索
深度搜索与广度搜索的控制结构和产生系统很相似,唯一的区别在于对扩展节点选取上。由于其保留了所有的前继节点,所以在产生后继节点时可以去掉一部分重复 的节点,从而提高了搜索效率。这两种算法每次都扩展一个节点的所有子节点,而不同的是,深度搜索下一次扩展的是本次扩展出来的子节点中的一个,而广度搜索 扩展的则是本次扩展的节点的兄弟节点。在具体实现上为了提高效率,所以采用了不同的数据结构.

评价:广度搜索是求解最优解的一种较好的方法,在后面将会对其进行进一步的优化。而深度搜索多用于只要求解,并且解答树中的重复节点较多并且重复较难判断时使用

第二部分 搜索算法的优化(一)
一、双向广度搜索
广度搜索虽然可以得到最优解,但是其空间消耗增长太快。但如果从正反两个方向进行广度搜索,理想情况下可以减少二分之一的搜索量,从而提高搜索速度。
二、玄学剪枝
最优性、顺序、可行性等

/
/
第三部分 搜索算法的优化(二)
该部分将谈到搜索与其他算法的结合。再看scu online judge的一道题目: 给定一个8 * 8的国际象棋棋盘。给出棋盘上任意两个位置的坐标,问马最少几步可以从一个位置跳到另外一个位置。(POJ1915类似)

该题目同样是求最优解,如果用一般的深度优先搜索是很容易超时的。如果用广度优先搜索,会消耗大量的内存,而且效率是很低的。这里,我们将尝试用深度优先搜索加动态规划的算法解决该问题。

将该棋盘做为存储状态的矩阵。每个矩阵元素的值是该位置到初始位置最少需要的步数。初始位置的元素值为0。其他位置的元素初始化为一个很大的正整数。首先 从初始位置开始深度优先搜索,例如某次从(i1,j1)到达位置(i2,j2),如果(i2,j2)处的值大于(i1,j1)的值加1,则(i2,j2) 处的值更新为(i1,j1)+ 1,表示从(i1,j1) 跳到(i2,j2)比从其他地方跳到(i2,j2)更优,不断的进行这个过程,直到不能进行下去位置,那么最后的目标位置的值就是解。这就是一个动态规划 的思想,每个位置的最优解都是由其他能够一次跳到这个位置的位置的值决定的,而且是它们中的最小值。同时,该动态规划又借助深度优先搜索这个工具,完成对 每个位置的值的刷新,可以算是一个比较经典的深度优先搜索和动态规划的结合。该问题还需要注意一个剪枝的问题,从起始位置到目标位置的最大步数是多少?经 过计算,最大值是6。所以一旦某个位置的值是6了,就不必再将它去刷新另外的位置,从而剪去了对很多不必要子树的搜索,大大提高了效率。
代码不贴了
/
/
/
/

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值