递归思想本身就比较难以理解,再加上回溯,整个过程更加扑所迷离。其实对于复杂的递归过程特别是非尾递归,很多时候已经不能一步一步地去分析函数调用,因为这样迟早会进死胡同。设计一个递归程序时,只要从数学逻辑上建立好递归模型,然后将该模型翻译成程序语言。
N皇后问题非常经典不需要重述,其实整个问题难点在于要找出所有的棋盘组合,试想如果只需要找出其中一种情况的话,问题就会简单很多。以五皇后问题为例,从递归思想来看,如果要将五个皇后放好,必须先将四个皇后放好,依次类推直到一个皇后的情况。这样实际上只需要写出摆放棋子的程序然后递归调用就好了。
但是这种做法会导致两个问题:1、如果皇后放到一半进行不下去了怎么办?2、得出了其中一种解后还想要其他解怎么办?其实这两个问题可以合并成一个问题,这时候必然要通过回溯,每一步中都必须提供一个能回到前一步棋盘状态的程序,因此在调用递归函数的后面应该有一个擦除当前状态的程序。
整个程序伪代码应该为
void putqueen
{
if(没有放完)
{
放棋子
if 找到一个解
输出解
else
递归调用putqueen
擦除当前状态
}