HDOJ ACM专题训练总结

(对不起我没有贴代码的习惯,不太喜欢抄板子。这篇内容只是用来复习回忆当时wa的死去活来的原因。

1 矩阵快速幂

   因为老刘的小课留的作业包含了矩阵快速幂,因此我也拿来练了练手,代码内容没什么难度,主要理解了矩阵的运算规则(期末熬夜肝线代,只有这个能用的上- -),还有快速幂的本质,基本代码方面就没什么问题,关键难的是如何运用,也就是如何推出辅助矩阵来达到目的,我的经验是(((((好像没有什么经验,主要是根据需要的递推式,把辅助矩阵需要的地方添上几个一,看起来没用的地方添上0,然后做一遍矩阵乘法,看看fn-1的位置现在是不是变成了想要的fn,如果不是,就略加修改。

   留几个经典题目方便以后复习用

   acm.hdu.edu.cn/showproblem.php?pid=1005

   acm.hdu.edu.cn/showproblem.php?pid=1021

2.搜索(dfs,bfs)

(因为操作失误,我码了接近一千个字的小段落就这么消失了,我凭着记忆重新码一遍吧)

搜索算法的整体理念其实比较好懂,因为说到底了其实是暴力枚举,只不过比forforfor等循环要高级很多,引入了当前状态下一状态,还有边界的概念,加上递归与剪枝,初学搜索的时候头都给吓掉了,后来发现这个算法只是为了其他算法做铺垫。

裸搜索的题一般挺有意思的,题目大多与走迷宫相关,(这个算法其实在一定程度上告诉我们陷入困境不要乱了脚步,要有规划的一步步执行,也不要乱了头脑,净做无用功,手动狗头)。说说题目的难点,递归和队列的思想可以很好地作为启蒙,当然我也不叙述过多,主要谈谈剪枝。

我遇到的题目关于剪枝一般都是对于回头路的处理,这里我以广度优先搜索(bfs)为例,最简单的例子就是求最短路,从起点开始往外一层层拓展,每一层的步数都保持一致,在队列中先到达终点的就一定是最短步数,这里涉及到一个必要剪枝,也就是对于每一层来说,上一层的路不会在这次拓展中再走一遍,因为来回走是必然是要多浪费几步的步数才能走到,所以我们会用一个标记数组来标记之前走过的路,标记过的路就不会拓展,没标记过则往下拓展,这也是最基本的思想,当然题目可不会让你如此轻松得逞

有一种类型的题目是要在规定时间内逃生,给你一个场景的迷宫,让你判断是否能成功逃离,加了一个额外条件就是地图上存在时间重置器,也就是说某种程度上你踩了时间重置器的话,你的剩余时间就会增加,更有利于逃出迷宫,那么问题来了,如果这个时间重置器在一个死胡同里,你要不要去踩,你踩了的话该怎么出来,走回头路吗,那如果这个回头路能走的话,是不是代表从起点出发的回头路都能走,如果不是的话那哪些回头路能走,哪些回头路又不能走呢,该如何去判断呢,如果按照这样的思路出发,那我们应该能轻松得到一个结论,要对标记量做一个处理,标记量用来标记当前剩余时间,如果你此时踏上去的剩余时间要比这条路之前标记的剩余时间要久的话,那踏上去就毫无问题,否则就跟走回头路没有什么区别,这里有一点点贪心的思路,也就是走的每一步一定要保证是有意义的。

最后还想说一个关于搜索的比较厉害的题目,就是我们专题的最后一题,胜利大逃亡(续),题面链接会在下面给出,这一题不同于炸弹求生的是,除了要考虑时间的问题,还要考虑另外一个状态,也就是钥匙,地图上有类似于障碍的门,这些门标号从a到j,可以通过捡对应的钥匙来开门,解除障碍,那这个条件的加入导致了什么,导致了先走到的路不一定是最完美的路,因为钥匙在离门比起点离门更远的地方,所以不能单单通过时间来做标记量,这些经历了专题前面的题的毒打的同学应该很容易想到,所以我们要用钥匙的状态和时间的状态两重标准来判断这个路该不该走,如果你拿着a钥匙走过了一片路,恰巧有一条路慢一些,先去拿了a和j钥匙,再来走这一片路,显然是要将路的状态更新的,因为如果终点周围是j门,那只有j钥匙才能打开。 钥匙的状态容易想到,那该用什么去记录钥匙的状态呢,我一开始的思路是,用1-11给a-j钥匙赋值,每一把钥匙有不同的值,那他们的和也会不一样,踩到路上的话,判断和是不是相同就可以了,不出所料的wa了,为什么呢,我想了想,1-11的值,和的组合太多,很可能会重复,比如1+4=5,2+3=5,拿到ad钥匙走过的路,换做bc钥匙就不能再继续走了,这样就很吃亏,很可能把最优解覆盖掉了,那怎样才能保证这些钥匙的赋值不会让和有重复呢,我思考了一会儿决定用2 4 8 16…1024这些值来代替1-11,因为打了几遍草稿,好像这些加起来并不会有重复的和(看了题解才知道这是二进制的原理),于是我在结构体内开了一个1030大小的数组来记录钥匙是否获得,还有一个sum记录钥匙的状态,每次走路,用时间和sum来更新路的状态,果不其然,还是过不了,mle了,当时的我因为被毒打太多,认为自己思路错了,但是想不到更好的解法,于是就去搜索了题解,恍然大悟,因为sum不会重复的性质,可以轻松从sum来推出某把钥匙是否获得,就避免了在结构体里开1030这么大数组,(我的二进制启蒙也是在这里开始的),于是我用题解的方法ac了以后,发现自己还能再缩小一倍数组的大小,可以从1-512这样记录,幸运又不幸的是,ac了,为什么不幸我就不说了qaq

http://acm.hdu.edu.cn/showproblem.php?pid=1072

http://acm.hdu.edu.cn/showproblem.php?pid=1175

http://acm.hdu.edu.cn/showproblem.php?pid=1429

http://acm.hdu.edu.cn/showproblem.php?pid=1254

搜索也没什么好讲的啦,留一下上面的题。

3.最短路(带权值的图,dij,bellman,floyd等算法

最短路的题变化很多,裸的最短路也基本是不太可能,不过在算距离上还是贴近算法本身,以目前接触到的题目境界来看,大概分为三种求距离的类型,第一种是询问多次,求某点与某点之间的最短路,这种两个点都没有固定的题目自然是floyd比较靠谱,不过floyd的复杂度在n的3次,所以题目数据范围太大就没有办法,但我现在还没有碰到很多用floyd解的题,如果有也比较简单,其次就是求一个固定的点到其他点的距离,这个要依图的类型来看,稠密图(边的条数比较多,点的个数比较少)一般使用dij来求,而稀疏图则是用队列优化的bellmen来做(其实bellmen以前是被我冷落的一种算法,直到3.1晚上的那场CF,我看到数据就知道只能用bellmen来解了,所以临场学习了一下,还不太熟练,在没用队列优化以前是tle的,后来用了队列优化才过,所以这是对我算法掌握的一种警示吧,如果熟练的话,这题我应该能少半个小时去解,估计就上1750了(求求不要嘲讽我qaq)

就到这吧,我自己也没有精通最短路有关的算法,只能当做现阶段学习的一个小小总结,希望将来有一天我也能发表一些专业的解析文章

贴一个题

(http://codeforces.com/contest/1321/problem/D)(感觉很适合作为一个最短路的巩固题

4.trie树(字典树

一种关于树的应用,略微谈一点目前对树的一点点理解,我认为树比较神奇的地方是树上的一个个节点的地址都不是连续的,他们在结构上是连续的,但是在编码时的地址却不是连续的,而节点的地址中存放了他儿子节点的地址,这样达成了连接的作用,便于查找与修改,并将一连串连续的节点可以当做一个整体,并且某些整体的公共节点可以共享,这样就减少了空间的浪费,与查找时时间的减少(只能感叹人类智慧的伟大啊啊啊啊)trie树只是树的一种应用,树在我目前看来应用更为广泛的是二叉树的模式,也就是每个节点有两个儿子,最神奇的事情发生了,如果按照一层一层从左到右来给每个节点编码,你会发现一件神奇的事情,也就是如果假设节点编号为n,那么他的左儿子的编号是2n,右二子的编号是2n+1,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值