前言
虽然这样比喻并不恰当,但是搜索算法就像是加强版的查找算法。你不再是研究一个具体的数字群体,而是寻找一条路径,一种方法,以达到某个明确的结果,你能研究的问题变多了。
关于搜索回溯算法的优化研究可以是很深刻的,现介绍回溯中最简单的一种——走迷宫。
一、基本思路
所谓走迷宫,专业一点的名字是“深度优先搜索”。
下面引用一段百度百科的定义:
搜索算法实际上是根据初始条件和扩展规则构造一棵“解答树”并寻找符合目标状态的节点的过程。深度优先搜索所遵循的搜索策略是尽可能“深”地搜索树。
这是什么意思呢?也就是说,我现在要走一条迷宫,我只知道两件事,我在入口,我要去出口。
前者是初始条件,后者是目标节点。
然后我就开始走,走路的方式无外乎三个原则:
1.直路,向前走。
2.岔路,先走左手边第一条(这个随便你)。
3.撞墙了,回到原来的岔路口。
1,2就是扩展规则,3就是回溯。
这样你最后肯定会走出迷宫,就是说,问题解决了,可行的线路已经被搜索出。
二、一个案例——素数环问题
自然语言:有多少种方法可以把1~20这些数字排成一个圆圈,使得两两相邻的数字之和均为素数。
我们会知道,走迷宫只要走出去即可,但此问题其实不完全如此,他的目标是“找出走迷宫的全部方法”。
也就是说,我们不是装上墙才往回走,而是在所有的路线完成后都往回走,另外需要一个计数器,每当我们走通了路,就会记一次数。
编程语言:我们设置第一个数为1(这无所谓)。
每一位都遍历2~20中未被选择(这有一套方法)的数,如果符合“和为素数”的延伸条件,就进入下一个数的选择。而如果始终找不到,就结束“深度搜索”,依次回溯到上一个路口(甚至直到开始)。显然,这是一个递归函数,因为我们要先向下搜索,回溯步骤必须暂缓执行。
代码实现:
上面是种类数(我没有消序除2)
下面是时间显示秒数。
每一次递归都有循环,每一次回溯回去,这个循环可能只是到了下一位······
可以说,这个算法对于计算机是非常痛苦的,但是对于人这是最好理解的基础写法,还差很多优化。
三、警告
我排出了每一个可能的a数组,但我什么都没有做,只是输出了一个总次数,没有每一次的排列。
要知道这不是浪费,因为这么大的计算量,你的界面上会不断打印、“闪过”巨量的数据,你看不过来,甚至怀疑程序出错了。(密恐,不上图了)
所以,要么去学优化,要么就老老实实的等80~120s。
the end
参考资料《信息学奥赛一本通》
活动地址:CSDN21天学习挑战赛