回溯的实质是什么?如何理解回溯算法?


答:回溯的实质是在问题的解空间进行深度优先搜索。DFS是个图的算法,但是回溯算法的图在哪里呢?我们把解空间的一个状态当做一个节点,由于解空间非常庞大,这个图就大到无法想象了。

举个例子吧,比如全排列问题,对于n个元素进行全排列,一共有n!种可能,比如n=9时,一共有9! = 362880种排列。初始化,我们什么都没有,定义如下状态

#define PT_SIZE 9
class PTState
{
int m_solution[PT_SIZE];
int m_arranged;
};

其中m_arranged表示已经在m_solution中排列的数字,刚开始时啥都没做,当然是m_arranged为0啦,而m_solution这个数组是用来放要排列的数字的,比如

 

123456789对应于m_solution[i] = i + 1

 

那么接下来要做啥呢?当然是开始排第一个数了,也就是要填m_solution[0]啦,这时你有多少种选择呢?嗯,当然是1, 2, 3, 4, 5 ,6, 7,8,9种,这还要说吗?那么先尝试谁呢?

从小到小依次填好了。

 

下面这个图是n=3时的解空间搜索图,其中白色的节点是初始节点,一个数都没填,第一行全是问号,第二行有个标记,表示还没有排列一个数。当第一位选1的时,节点变成了紫色,此时m_arranged = 1, 还剩两个数没有填。这时填第二个数时,发现只能填2或者3,当填上2后,又到了下面一个蓝色的节点,该节点的状态中m_arranged = 2,再扩展下去,第三位只能填3,于是到了最下面的黄色节点。

此时,再想扩展黄色节点时,发现m_arranged已经是3了,这时表明这是一个最终的节点,无法再扩展了,于是得到了一个排列。那么其他排列如何得到呢?回到黄色节点上面的蓝色节点,我们发现第三位除了3再也不能填其他数了,没法继续扩展,没办法,再回到上面的紫色节点,这时发现,紫色节点中的第二位还能填3,于是可以顺利扩展到下面的第二个蓝色节点。这个过程便是回溯和扩展节点的主要过程。

 

在编程实现时,由于我们无法存储所有的状态节点,只能保持一个当前状态,然后通过扩展到下一个节点,来修改当前节点的状态,但是当扩展完一个节点时,必须得恢复到原来节点的状态,才能进行下一个扩展。这个逻辑写成代码便是如下形式:

 

Solve (State & state)
for action in A
if state.CanMove(action)
state.Forward(action);
Solve(state)
state.Recover(action);

 

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM