简单算法复习

个人认为,信息学竞赛中最难的部分,要数算法的学习和灵活运用了吧。其实算法呢,讲讲概念很好理解,可一道题目中,就千变万化,纯看个人造诣了。本人在这方面比较弱。。。讲的太浅显,或者有什么问题还请不吝赐教。

1.搜索

好的搜索是一门艺术,是优雅的暴力。

这几天的的模拟赛告诉我一个真理:练好搜索!练好搜索!!练好搜索!!!毕竟我们实力有限是吧。所以说正解不强求,但暴力分怎么也得拿一点啊。

无奈基础太差,优化算法涉猎较少,现在摆出这几天刷的题吧。

求先序排列:大水题(PJ),但是让我对树的先序,中序,后续排列有了一些理解

高手去散步:DFS水题

家族:BFS水题,但是其中对字符串的处理值得学习

NOIP2003传染病控制:树上搜索,自习想想还是比较好理解的

*NOIP2016愤怒的小鸟:搜索策略不再是单纯的枚举,细节方面也有很多注意的地方。

*NOIP2004虫食算:有技巧的搜索

*NOIP2015斗地主:较复杂的搜索,代码量大。

其他OJ上的题,看了一些但是没写了。只能说自己刷题量还是太少了吧。

需要学习的部分:DFS剪枝,迭代加深,双向广搜,启发式搜索。

2.分治

这几天学的东西,大部分的与分治有关。

分治,字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。上面详细讲的树状数组和线段树,其实都是分治思想的体现

也不多讲,以题目为例吧:

平面内最近点对:好题嗯。大局分治,局部暴力。

最小三角形:和平面内最近点对差不多,是落实的好题。

*BZOJ4985: 评分:二分+DP?思想极其巧妙。

*BZOJ4592:脑洞治疗仪:线段树/珂朵莉树高级题目。

以上分治题目的质量还是非常高的,值得好好咀嚼吸收。

*3.动态规划

已放弃治疗。。。

如果没退役我一定恶补DP!!! QAQ

4.图论

划重点好啦其实就是板子比较多。

1.最短路

 Dijkstra算法(堆优化):

priority_queue < pair <int,int> > q;    //优先队列(大根堆)修改为小根堆
int dis[N];                     //dis数组:dis[i]表示i点到起点s的距离,初始化为无穷大
bool v[N];                          //v数组:节点是否被松弛过
void Dijkstra(int s)
{
    for(int i=1;i<=n;i++)
    dis[i]=2147483647;
    dis[s]=0;
    q.push(make_pair(dis[s],s));     //初始节点入队
    while(q.size())
    {
    int x=q.top().second;q.pop();         //出队
    if(!v[x])            //如果没被松弛过
    {
        v[x]=1;                     //记为已松弛
        for(int i=head[x];i;i=e[i].nxt)     //遍历所有邻边
        {
        int y=e[i].to;
        if(dis[x]+e[i].v<dis[y])                //如果能松弛
        {
            dis[y]=dis[x]+e[i].v;               //更新
            q.push(make_pair(-dis[y],y));    //入队
        }
        }
    }
    }
}

至于SPFA...求负环还不是很熟。不写了。

*地铁涨价:最短路+动态加边

*2.二分图匹配

学了但不熟。不写。

3.最小生成树

算法实现挺容易的吧。$Kruskal$就是并查集+贪心。

不过关键的一点就是看你能不能将题目转换成最小生成树的题目。就比如上次选拔考试 水滴 那个题,表面上是暴力模拟,实际上可以建图+最小生成树来做。

还有一个题目:洛谷P1550:一点思维就能转化为最小生成树的水题。

4.强连通分量

Tarjan不熟。。。先把板子背了吧。

DFN[ i ] : 在DFS中该节点被搜索的次序(时间戳)

LOW[ i ] : 为i或i的子树能够追溯到的最早的栈中节点的次序号

void tarjan(int i)
{
    int j;
    dfn[i]=low[i]=++time;
    in[i]=1;sta[++top]=i;
    for (int e=head[i];e;e=edge[e].next)
    {
        j=edge[e].to;
        if(!dfn[j])
        {
            tarjan(j);
            if (low[j]<low[i])low[i]=low[j];
        }
        else if (in[j] && dfn[j]<low[i])
            low[i]=dfn[j];       //注意细节
    }
    if (dfn[i]==low[i])    //判断条件
    {
        Bcnt++;
        do
        {
            j=sta[top--];
            in[j]=0;
            belong[j]=Bcnt;
        }while(j!=i);
    }
}

原文地址:https://www.cnblogs.com/Zerosking/p/10011086.html

时间: 2024-10-12 04:15:22

简单算法复习的相关文章

C语言排序算法复习

排序算法有很多种,这里在复习和分析的基础上,做一个自己的总结: 首先要知道有哪些排序算法,google一下,有云C语言7大经典排序算法(也有8大).主要包括冒泡排序,快速排序,选择排序,插入排序,希尔排序,归并排序,堆排序,8大的还有基数排序.各有各的版本,代码写法也各不相同.所以这里以整理思路为先,代码只是作为自己的一个备份. 搞清楚的概念:稳定排序和不稳定排序,就看序列中两个值相等的数,排完序之后的相对位置是否改变,如果改变了就不稳定. 内部排序和外部排序,只用到内存即可完成排序的就叫内部排

算法复习计划

写在前面 随着四月的到来, 离省选越来越近了. 从NOIP到现在, 学到了很多很多东西, 有的学的比较深入, 有的只是略知一二 从明天开始, 进行针对省选的算法复习计划. 省选前完成. 重点是对算法的理解和应用, 还会注重模板习惯的养成 计划内容 1. 数据结构 一直觉得我数据结构学的还可以, 不过列出来发现会的也没多少. 少就少吧, 省选够用就行... 线段树 树状数组 并查集 哈希表 STL treap splay 树链剖分 主席树(可忽略) 字符串(KMP, 后缀数组) 2. 图论 掌握经

算法复习-研一上

算法复习  包含主题: 贪心算法 , 分治法,动态规划,回溯法,分支限界,线性规划 关键词:最优子结构 Q:贪心与动态规划中间的联系和区别 p93 后面总结 (背部问题,0-1背包问题) 递归分治算法 基本思想:将一个大的问题分成若干小的子问题问题,分而治之 一般步骤:1.分解将原问题分为若干规模小,相互独立与原问题形式相同的问题   2.求解,求解各个子问题,当问题被划分的足够小的时候,就能很容易求解     3.合并,将子问题逐层合并,得到最后的解 经典问题 二分搜索: 合并排序(将想要排序

图的所有简单算法实现

包括邻接链表.有向无向图.带权图.增删顶点和边.查找.连通.DFS和BFS等.这只是一个最初版本,有些复杂的算法还没有实现. package structure; //图的邻接链表的节点 public class GraphListNode { private int vertex;//图的顶点 private int weight;//边的权重 private boolean visited;//是否访问过 //带权重图的节点 public GraphListNode(int vertex,i

排序算法复习

排序算法复习 作者:vpoet mails:[email protected] 注:转载请注明出处 #include <iostream> #include <windows.h> using namespace std; void Bubble_Sort(int UnSort[],int length); void Select_Sort(int UnSort[],int length); void Insert_Sort(int UnSort[],int length); vo

根据权重挑选通道的简单算法

当存在一批通道,根据权重,选择哪个通道去使用的简单算法. 利用随机数,数据区间,来获取通道. 通道权重越大,单位时间内使用该通道的概率会大一些. 代码 1 //利用了一个权重区间的比例问题,抓取随机数的可能性,来体现权重思想 2 public static void main(String[] args) { 3 //定义三个通道的权重,按随机数选拔使用哪个通道. 4 //A 10 B 70 C 30 5 //从数据库查询出list集合 6 ChannelD A=new ChannelD("A&

JS 简单算法

//分别使用while/do-while/for循环实现10的阶乘(使用递归算法) //do-while循环实现10的阶乘 var i=1; var resule=1; do{ resule *= i; i++; }while(i0;i--){ if(a%i == 0 && b%i == 0){ console.log(i); break; } } //for循环求最小公倍数 for(var i=max;ib){ min = b; max = a; }else{ min = a; max

【线性表基础】基于线性表的简单算法【Java版】

本文描述了基于线性表的简单算法及其代码[Java实现] 1-1 删除单链表中所有重复元素 // Example 1-1 删除单链表中所有重复元素 private static void removeRepeat(LinkList L) { Node node = L.head.next; // 首结点 while (node != null) // 一重循环,遍历L中的每一个元素 { // Object data=p.data; Node p = node; // q结点的前驱 Node q =

数据结构与算法复习(一) 排序算法(I)

这篇文章将会介绍最常见的排序算法(使用 JavaScript 语言实现) PS:这里我会尽量使用语言无关的语法去写,大家不要太在意语言,重要的是算法的实现思路 1.冒泡排序 将数组分为有序区(左边)和无序区(右边) 每次从无序区的最后一个元素开始,一直向前冒泡到无序区的第一个位置,使其变成有序 function swap(A, i, j) { if (i === j) return [A[i], A[j]] = [A[j], A[i]] } function bubbleSort(A) { fo