这周除了接着看上次没看完剩下的题,主要的就是做题了
我把这周新学到的和以前还没总结过的以及做题心得再主要说一下
这周做题和看到的主要是以下这几类
我把这周做题时遇到的某几类题简单归了一下类然后总结
遍历节点图
搜索和有向图
2、P2853 [USACO06DEC]Cow Picnic S
从这些题中学到的一点东西以及心得
1、一道思维题,给出某两节点之间相连,自定义方向使最长的一条路径最短
但只要发现了它的规律即可破题 使每个节点全为入度或全为出度时最长路最短,即对于深度为奇数的点 uu,可以把连接它的儿子 vv 的边定向成 u->vu−>v;对于深度为偶数的点,反过来,变成 v->uv−>u。
2、无权的有向图也可以用vector存储。
3.两节点之间有多条连边求最大路径时可以一直用max只保留两点间大最大路径长度
4、在有向图中,要注意有环和无环是不一样的,有时需要判断其中是否会出现环,在搜索的过程中,不回溯时,若能访问到已标记的节点则就是环
5、有环的时候不能用拓扑排序,如果确定无环,则可以用拓扑排序,先找到一个入度为零的点,(可以定义一个数组,每输入一组方向u->v时便使a[v]++,输入完a[i]值为零的i则入度为0)然后就可以用拓扑排序输出一个正常的序列了
6、.可以用map[a][b]=c记录从a点到b点这条路的权值为c
无向图
1、第一题是一个染色问题,染色问题就是将不同的颜色(要求)按要求分布在一张图的若干个点上,这个题就是要求相邻两个点的颜色不能相同,如果染到最后发现涂完这个之后他和其余相邻的颜色相同了,那么就染色失败,不能完成(但是要注意整个大图不一定是连通的,所以要分开给每一块连通图染色)本题dfs染色核心代码
void dfs(int x)
{
for(int i=1;i<=b[x][0];i++){
if(f[x]==f[b[x][i]])
{cout<<"Impossible";
return;}
if(f[b[x][i]]==0)
{ f[b[x][i]]=3-f[u];
if(f[b[x][i]]==1)
t++;
else tot++;
dfs(b[x][i]);}}}
2、在遇到无向图时可以用邻接表(稀疏图)或邻接矩阵(稠密图)
(涉及权值时别忘把数组预处理全赋为一个最大值0x7f)
3.dfs无向图的大概思想就是先找一个起点然后搜索和他相连的没有被标记的结点如果都被标记就回溯反回到上一个结点再去搜索别的结点,直到所有的点都被标记。
4.可以用map[a][b]=c记录从a点到b点这条路的权值为c
但是注意不要忘记map[b][a]=map[a][b]!! 只能在无向图中写
搜索与二叉树
1、在树中,求深度和宽度的方法
在用floyd循环后,深度就是 max(a[1][i],nowmax)(循环时b[a[1][i]]++;记录每一层节点数,)
宽度即为 max(b[i],nowmax)
2、树可能是空树,有个别时候需要验证是否为空
3、树和dfs:我一般都是先遍历根节点,然后再左子树右子树,感觉这样比较好写,一般都是用堆栈来实现,栈是后进先出所以可以先将右子树堆栈然后再让左子树进栈这样左边就会出现在栈顶了)
4、树和bfs:用队列实现,先找根节点,然后推入队列,因为队列是先进先出,所以可以接着推左子树结点然后再推右子树结点,这样就能保证先搜的是左子树
ps:找根节点时就是找入度为零的点,也可以用定义一个数组实现,每输入一组父节点到子节点:u->v时便使a[v]++,输入完a[i]值为零的i则入度为0
然后记录一个dfs+记忆化搜索的题:有点类似于剪枝,优化时间
[NOIP2017 普及组] 棋盘 - 洛谷 |
搜索与地雷
用到三个函数,分别是输入时每遇到雷时便将此雷周围八个格子的数字+1(这样遍历后就能求出地雷数字图了),第二个函数便是判断周围八个有无空格,第三个是遍历将没有雷的标记并继续搜索八联通把没有地雷的标记,通过遍历地图能求出连通块的数量,然后再通过函数一再加上周围八格无雷的数字的数量
做题注意和做题小心得
ps1:在搜索中要注意的是,图不一定是全部连通的,也可能是分开成了好几块,要对每个连通块都搜索,做题时好几次都没有注意然后导致最后结果是错的,要时刻注意
ps2:邻接矩阵 开始要预处理使二维数组所有数字最大(可为0x7f)因为边权有可能为负的,怪不得在做题的时候看着题解上说要预处理,我觉得不加也可以结果就错了,加上那一段就对了,上课问费老才注意到边权也可以是负的,呃呃呃大意了
ps3:数组赋值不一定是0更方便 可以用memset赋值-1 不与题中数字冲突,更方便
ps4:要注意看数据范围需不需要用long long(怎么总是在这里栽跟头)有的题即使表面上看起来不需要,但是当结果累加时可能就超过了一定的范围
本周心得体会
截止到现在仅仅把费老给的那九十多道搜索看了,好像感受到了和以前不一样的感觉。
以前只是单纯看题,然后像一个机器一样去做题,现在感觉做的题目其实可以变相反应去解决生活中的问题呀。 以前感觉算法只单单是比赛算法,从没把它和实际生活联系起来,但现在,果然,见多识广(啧啧啧虽然不算多),见识到了好多多种多样的题,好多都是和生活息息相关的呀,
那个扫雷,以前经常玩,盲目的点格子或者是似懂非懂的经过心里的小计算去点有把握的格子,但从没想过棋盘上面的数字竟也可以用代码算法去实现从而确定是数字几,(虽然现在只是很简单的去实现一丁点,但让我感悟了许多)
扫雷,走地图,食物链(要是生物考试能敲个这代码就不用担心自己查错了哈哈哈小声说),还有后边几个都是游戏题,打怪、消耗能量(感觉有点难 需要考虑很多),虽然是最基本简单的游戏,但实现这就已经够整我的了,那些大游戏不就是基于这些最最最最最最基本的思想么(虽然这和那相比起来可能过于简单)
看了三周的搜索,好像也理解了为什么这个搜索要看这么长时间,前天和一个大一下学期也选修acm的学长聊了会,他说几乎很多题都能用搜索算法的思想解决,好像确实是这样,放在平常来看,举个例子,在导航时,往往会给你推送一个最优的路径解,这不就是整天做的搜索地图题演变过来的么,果然知识都是有用的学了就一定能和实际生活联系起来并用到
果然看得多点脑袋里可能真的会多一点东西,这三周的搜索让我受益匪浅,而且这好像也是头一次连续坚持了三周多去干一件不是常规的事,真的会慢慢改变吧!暂且先对搜索告一段落吧,期待接下来的并查集带给我新的思路和启发