• 【总结】NOIP复赛来袭,各种算法经验大杂烩


    NOIP来了,好紧张~

    以下将这进1年学的东东汇总一下,最后还有临场经验!


    【递归】【递推】递归是在学完基础语言过后的第一个“算法”,哎,说白了就是函数调用自身,想当初完全无法理解,有了递归,斐波那契啊,汉诺塔啊都很简单了,这也为后面打下了基础,当然,纯递归也很容易超时,没办法~于是就有了记忆化递归,递推嘛差不多,只是用了for循环,加上数组来算,举个栗子:

    /*
    记忆化递归解决斐波那契数列
    */
    #include<cstdio>
    long long a[92];//经测试longlong最多能装下第91个数
    long long x(int k)
    {
    	if(k<3)
    		return k;
    	if(a[k]==0)
    		a[k]=x(k-1)+x(k-2);
    	return a[k];
    }
    int main()
    {
    	int n;
    	scanf("%d",&n);
    	printf("%I64d",x(n-1));
    }
    

    #--------------------------------------------------------------------------------#

    【回溯】【DFS(深搜)】这种算法就是建立在递归之上的,大体思路就是:找到最深处(冲啊!!!),返回,找第二种,再返回……直到找完,解决得了很多迷宫问题(你最好不要用此算法尝试数据大得恶心的最优解题,不然超时超得你透心凉心飞扬),顺便刷刷阅读量:

    【NOI OJ】8783 单词接龙

    【NOI OJ】1818 红与黑

    更多搜索题目请点击题库

    #--------------------------------------------------------------------------------#

    【BFS(广搜)】

    【BFS】广度优先搜索&【DFS】宽度优先搜索

    #--------------------------------------------------------------------------------#

    【枚举】世上最强骗分技巧,传说中的暴搜就是它了,任何题都可以枚举,依靠计算机那每秒10亿次的超级运算能力,我们每次都能完美地——超时,当然也有题完全可以枚举,事实上只要你有超过3个for循环,基本上是超时了,题型:

    【NOIP普及组】2016年模拟考试(11.5)——火柴棒等式

    事实上枚举过了很多题,都水得不想写了……╮(╯▽╰)╭,题库

    #--------------------------------------------------------------------------------#

    【贪心】最好理解的一种较高级算法,不停地找最大的(真是贪婪),最简单的:一个数字矩阵,从每行选一个数,使其和最大。就选每行最大的即可,题型:

    【NOI OJ】1797 金银岛

    【NOI OJ】3528 最小新整数

    更多贪心题目请点击题库

    #--------------------------------------------------------------------------------#

    【DP(动态规划)】和递推很类似(只是类似而已),主要是满足一下条件可以尝试:

    1.数据规模不大;

    2.像贪心,又没办法贪的(反正就是很恶心的,选最大的不行的题);

    3.满足无后效性原则:当前的最优解与后面无关,只与前面有关;

    4.满足最优化原理(最优子结构性质):从起始到结束的最优路径中的每个节点都为当前最优;

    说这么多,到底怎么“规划”呢?

    首先划分阶段,使每一个阶段与前面建立起联系;

    然后写出状态转移方程(最难的一步),说白了就是将当前最优解用之前的表示出来,这是一个漫长的过程,熟了一下就行,不熟绞尽脑汁也不知道;

    接着需要寻找边界,你总不可能让它无休止地找吧……当然有最后就又开始,一定要注意初始化;

    最后就是程序的实现了,这个非常简单,不多说。

    题型:

    【NOI OJ】4977 怪盗基德的滑翔翼

    【NOI OJ】2728 摘花生

    更多题目请点击题库

    #--------------------------------------------------------------------------------#

    【图】

    一大波文字来袭,做好心理准备……

    首先,图是什么?图就是图,请注意,图就是图,请记住,图就是图!好吧,将点用边连起来的就是图,如下,事实上,图是一种数据结构,但我还是归在了算法~

    然后,有几个概念(天哪噜,又有概念了,肿么办!!)

    【有向】很好理解,点1可以到点2不代表点2可以到点1就是有向。

    【无向】相反,点1可以到点2便代表点2可以到点1。

    【权值】一条边的大小(也可能是费用、长度什么的)叫权值。

    【结点的度】以此点为终点的边的数目。

    【结点的出度】简单点,此点可以出去的边的数目。

    【结点的入度】反之,有几个点可以一步到此点,入度就是几。

    【回路】从此点出发能回到此点便是回路。


    注意以下都是归属于图的

    1.【树】

    树嘛……以前觉得好深奥,其实,简单点,一个有向无回路图就是树,如上(哇塞,真的好像一棵树诶!!)。

    【二叉树(BT)】咳咳……二叉树,理论最多的东西,让我们继续愉(xiang)快(gu)地不聊了吧。

    好像还没说二叉树是啥,反正就是每个点的下面的结点(称之为儿子)最多只有2个的树。

    好的,关于二叉树有两个东西:完全二叉树和满二叉树。

    【满二叉树】除最后一层的结点外,其他的都有两个儿子的二叉树,说起来好吓人,其实很简单。

    【完全二叉树】连续的二叉树(好像这解释很智障,但我真的不知道怎么解释了,图中自有真相):


    树的题嘛……

    可以点这里<--


    【堆】这个看这里<--


     【最短路径】:最简(bao)单(li)易(chao)懂(shi)的代码:Floyed,稍(bu)微(yi)难(chao)一(shi)点的:Dijkstra,请参看:
    【图】最短路径——Floyed算法和Dijkstra算法

    如果你想更快,那就上天吧……

    好吧,当然有更快的FordSPFA,这东西最适合装逼了,当然装逼是有代价的——复杂——想知道自己点击前面。


    【并查集】,请看这里<--


    图最容易考到的都差不多了,呼……

    #--------------------------------------------------------------------------------#

    另外的数据结构:

    【栈】最形象的比喻:一个杯子,只能从上面进,上面出。什么意思?就是先进去的后出,后进去的先出,如图。


    假如有一列数:1,2,3,4,让我们来模拟一下栈:

    初始:栈为空。

    ①1入栈。栈中的数为(从下往上):1;

    2入栈。栈中的数为(从下往上):1,2;

    ③3入栈。栈中的数为(从下往上):1,2,3;

    ④4入栈。栈中的数为(从下往上):1,2,3,4;

    ⑤出栈(只有一种操作,因为你只能取出栈顶元素,不能取出中间的元素):4出栈,栈中的数为(从下往上):1,2,3;

    出栈(只有一种操作,因为你只能取出栈顶元素,不能取出中间的元素):3出栈,栈中的数为(从下往上):1,2;

    ⑦出栈(只有一种操作,因为你只能取出栈顶元素,不能取出中间的元素):2出栈,栈中的数为(从下往上):1;

    出栈(只有一种操作,因为你只能取出栈顶元素,不能取出中间的元素):1出栈,栈为空。

    就这样了,栈有什么用呢?首先最直观的:逆序输出一列数,当然你可以用数组,但是……一会再讲。

    事实上,递归就是栈的使用,只不过是一层存了很多条代码,而不是只存一个数。

    装逼程序(逆序输出):

    #include<cstdio>
    bool f=1;
    void go(int x)
    {
    	if(scanf("%d",&x)==1) go(x);
    	if(f) {f=0; return;}//因为用无个数的输入,所以要处理一下 
    	printf("%d ",x);
    }
    int main()
    {
    	int a;
    	go(a);
    	return 0;
    }
    

    注意,这样的无个数输入需要最后Ctrl+Z一下,代表输入结束,如果你用了freopen或者是机测就不用在意,反正这样写交NOIP不会错~

    然后要说的是,栈会溢出的!如果输入有超过2万的数,基本上是不行了,交上去会……运行错误。

    好的,栈也是有专门的容器的,你也可以不用递归:

    头文件:stack
    声明方式:stack <存储类型> 栈的名字;
    如:stack <int> a;
    入栈:栈的名字.push(入栈的数);
    如:a.push(x); a.push(2);
    返回栈顶元素的值(不删除此元素):栈的名字.top();
    如:x=a.top();
    删除栈顶元素(不返回此元素的值):栈的名字.pop();
    如:a.pop();
    判断栈是否为空:栈的名字.empty(); 空返回true,反之返回false。
    如:if(!a.empty()) return 0;//如果栈为空便结束
    返回栈中元素个数:栈的名字.size();
    如:len=a.size();

    关于栈就这些了,接下来还有队列【吐血】……


    好的,接下来是队列了

    【队列】最形象的比喻:一个管子,只能从后面进,从前面出。什么意思?就是先进去的先出,后进去的后出,如图。


    假如有一列数:1,2,3,4,让我们来模拟一下队列:

    ①1入队。队列中的数为(从左往右):1;

    2入队。队列中的数为(从左往右):1,2;

    ③3入队。队列中的数为(从左往右):1,2,3;

    1入队。队列中的数为(从左往右):1,2,3,4;

    ⑤出队(只有一种操作,因为你只能取出队头元素,不能取出中间的元素):1出队,队列中的数为(从左往右):2,3,4;

    出队(只有一种操作,因为你只能取出队头元素,不能取出中间的元素):2出队,队列中的数为(从左往右):3,4;

    ⑦出队(只有一种操作,因为你只能取出队头元素,不能取出中间的元素):3出队,队列中的数为(从左往右):4;

    ⑧出队(只有一种操作,因为你只能取出队头元素,不能取出中间的元素):4出队,队列为空。

    队列又有什么用呢?首先肯定是广搜啦,然后队列里还有一种极其恶心的优先队列……不想说什么了,其实就是堆而已。

    至于例子嘛,自己看广搜(我不会告诉你我是用数组模拟队列的

    如果要用标准队列……如下:

    头文件:queue
    声明方式:queue <存储类型> 队列的名字;
    如:queue <int> a;
    入栈:队列的名字.push(入栈的数);
    如:a.push(x); a.push(2);
    返回队头元素的值(不删除此元素):队列的名字.frond();
    如:x=a.frond();
    删除队头元素(不返回此元素的值):队列的名字.pop();
    如:a.pop();
    判断队列是否为空:队列的名字.empty(); 空返回true,反之返回false。
    如:if(!a.empty()) return 0;//如果队列为空便结束
    返回栈中元素个数:栈的名字.size();
    如:len=a.size();


    如果你以为完了,呵呵,还有,链表!

    #--------------------------------------------------------------------------------#

    好吧先说到这,有时间再写                                                                                                                                                             By WZY

  • 相关阅读:
    Red and Black POJ
    Catch That Cow HDU
    Lotus and Horticulture HDU
    进击的绿色
    北京办护照
    女码农真诚征gg
    bitset
    long long
    cnblogs latex公式
    2050 Programming Competition (CCPC)
  • 原文地址:https://www.cnblogs.com/LinqiongTaoist/p/7203759.html
Copyright © 2020-2023  润新知