回溯法的分析及N皇后问题

所谓的回溯法实质就是深度优先搜索,在每个路径上一直向前寻找,到达某个结点不满足约束函数时,就回溯到其父结点,从父结点的其他子树向下寻找。

当某条路径可以一直伸展到叶子结点时,就在叶子结点上继续遍历,遍历的结果必然是叶子结点的某种情况不满足约束函数,这时就要回溯到叶子结点的父结点,从父结点的其他子树向下寻找,这个子树同样也要遍历叶子结点的所有情况。

回溯实际上是递归的展开,但实际上两者的指导思想并不一致。

打个比方,递归好比是一个军队要通过一个迷宫,到了第一个分岔口,有3条路,将军命令3个小队分别去探哪条路能到出口,3个小队沿着3条路分别前进,各自到达了路上的下一个分岔口,于是小队长再分派人手各自去探路——只要人手足够(对照而言,就是计算机的堆栈足够),最后必将有人找到出口,从这人开始只要层层上报直属领导,最后,将军将得到一条通路。所不同的是,计算机的递归法是把这个并行过程串行化了。

而回溯法则是一个人走迷宫的思维模拟——如果他没有办法在分岔口留下标记,他只能寄希望于自己的记忆力。


1.递归回溯法

一定要注意:void型递归函数的返回是隐形的,即当前层条件不满足,就会自动返回到上一层。

下面的Queen代码中,如果当前层没有找到合适的位置放置皇后,即循环体中的部分就不会执行,自然也不会执行循环体中的递归函数 Queen(row+1); ,说明上一行选择的列不合适,递归返回到上一层,执行Queen_array[row]=0; 然后col++。重新查找合适的列,如果本层递归仍然查找不到,就继续向上一层回溯,执行Queen_array[row]=0; 然后col++ ……


#include
#include

#define N 8

int count=0;
int Queen_array[N]={0};

int Pos_Feasible(int row,int col)
{
	int i;
	for(i=0;i

2.回溯法

由递归回溯法的分析,我们可以知道,如果一直向上一层回溯,使得回溯到最上层(第一行),col 也增加到了最后一列,但仍不合适,程序仍要向上层回溯,可是没有上层函数了,此时就退出了程序,我们可以利用这一点(把行号作为循环条件,如果行号小于1了则退出循环——此时就是回溯到了最上层仍找不到合适的列还想再向上找的情况)作为循环的条件而不需要递归。

程序如下:

#include
#include
int x[100];

int count=0;

bool place(int k)//考察皇后k放置在x[k]列是否发生冲突
{
    int i;
    for(i=1;i=1)
    {
        x[k]++;   //在下一列放置第k个皇后
        while(x[k]<=n&&!place(k))
            x[k]=x[k]+1;//搜索下一列
        if(x[k]<=n&&k==n)//得到一个输出
        {
            for(i=1;i<=n;i++)
                printf("%d ",x[i]);
            printf("\n");
            count++;
        //return;//若return,就无法在叶子结点上继续遍历( x[N]++; ),就找不到可以让它回溯的点,也就无法回溯,则只求出其中一种解
        }
        else if(x[k]<=n&&k

3.精简版 ( 由1演化而来 )

#include
#include

#define N 8

int count=0;
int Queen_array[N]={0};

void print_result( )
{
	int i;
	for(i=0;i


你可能感兴趣的:(C/C++,算法)