简单算法复习

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

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);
	}
}

posted @ 2018-11-24 09:52  Zerosking  阅读(134)  评论(0编辑  收藏  举报