回溯的概念参见:http://blog.csdn.net/jiecooner/article/details/8673321
解释几个地方:
解空间树:
并非就是一个真正用数据结构造出来的一棵树,当然也可以真的是,不过绝大部分时候不是,因为真正的树时间复杂度和空间复杂度并不是很优的;应该是这样理解:解空间树是抽象的把问题可能的解放置在一个棵树中的叶节点,要找到这个合适的叶节点要从根结点开始深度优先搜索,在这里就可以用到回溯法带来的好处,如果在访问到一个根结点时发现由这个根结点出发的所有分支一定不会得到一个正确的叶节点时放弃这个根结点出发的所有分支的搜索,直接跳到其兄弟节点,虽然这个解空间树并非一个真的树,但要对树的基本知识有点了解,
深度优先搜索:
http://baike.baidu.com/view/288277.htm
回溯一般是用递归实现:
举个例子怎么实现:
比如用递归解决阶乘问题:
int jieshen(int n)
if(n==1)
{
return 1;
}
return jieshen(n-1)*n;
这是阶乘,看得出这个每递归一次n减1,相当于是树的向下搜索,要想回溯那就相当于是
jieshen(n+1)*n
只是个思想;
下面看一下实现过程:
#include<stdio.h>
#include<string.h>
#define M 8
int IsTrue(int i,int j,int Q[M][M]);
void Queen(int j,int Q[M][M]);
int main()
{
int Q[M][M];
memset(Q,0,sizeof(Q));
Queen(0,Q);
getchar();
return 0;
}
int IsTrue(int i,int j,int Q[M][M]) //这个函数是判断该皇后放置的位置和前面以放好的皇后是否有冲突;
{
int s,t;
for(s=i,t=0;t<M;++t)
if(Q[s][t]==1&&t!=j) return 0;
for(t=j,s=0;s<M;s++)
if(Q[s][t]==1&&s!=i) return 0;
for(s=i-1,t=j-1;s>=0&&t>=0;s--,t--)
if(Q[s][t]==1) return 0;
for(s=i+1,t=j+1;s<M&&t<M;s++,t++)
if(Q[s][t]==1) return 0;
for(s=i-1,t=j+1;s>=0&&t<M;s--,++t)
if(Q[s][t]==1) return 0;
for(s=i+1,t=j-1;s<4&&t>=0;s++,--t)
if(Q[s][t]==1) return 0;
return 1;
}
void Queen(int j,int Q[M][M])
{
int i,k;
if(j==M) //递归结束条件
{
for(i=0;i<M;++i)
{
for( k=0;k<M;++k)
{
printf("%d ",Q[i][k]);
}
printf("\n");
}
printf("\n");
return;
}
for(i=0;i<M;++i)
{
if(IsTrue(i,j,Q)) //这一步很重要,在搜索过程中减枝
{
Q[i][j]=1;
Queen(j+1,Q);
Q[i][j]=0; //回溯
}
}
}