回溯法之N皇后问题(C语言)

合集下载

实验四 皇后问题求解

实验四 皇后问题求解

实验实习名实验二皇后问题求解(以下为参考内容,具体内容要求由课程在实验实习指导书中规定。

)一、实验实习目的及要求实验题目:皇后问题求解实验目的:1)以Q-皇后问题为例,掌握回溯法的基本设计策略。

2)掌握回溯法解决Q-皇后问题的算法并实现;3)分析实验结果。

二、实验实习设备(环境)及要求(软硬件条件)实验环境:计算机、C语言程序设计环境三、实验实习内容与步骤实验内容与步骤1.用回溯法求解N-Queen,参考教材算法思想,并实现你的算法。

要求:用键盘输入N;输出此时解的个数,并统计运算时间。

2.给出N=4,5,6时,N-Queen解的个数。

3.尝试增大N,观察运行情况;并理解该算法的时间复杂度。

四、实验实习过程或算法(源程序、代码)源程序:#include<stdio.h>#include<math.h>#include <time.h>int X[10];bool PLACE (int k){int i=1;while(i<k){if (X[i]==X[k] || abs(X[i]-X[k])==abs(i-k) )return false;i=i+1;}return true;}void main(){int k=1,n;int count=0;printf("请输入一个正整数:\n");scanf("%d",&n);double duration;clock_t finish, start;start = clock();while (k>0) //对所有行执行以下语句{X[k] = X[k]+1; //移到下一列while(X[k]<=n && !PLACE(k) ){X[k] = X[k]+1; //移到下一列,再判断}if (X[k] <= n) //找到一个位置{if (k==n) //一个完整的解{//printprintf("the soution is:");for (int t=1;t<=n;t++)printf("%3d",X[t]);printf("\n");count +=1 ;}else{k=k+1;X[k]=0;} //转向下一行}elsek=k-1; //回溯}finish = clock();duration = (double)(finish - start);printf("\n the number of the solutions is %d \n", count);printf( "The count time is %2.6f seconds.\n", duration);}五、实验实习结果分析和(或)源程序调试过程(一)算法理论分析使用回溯算法求解的问题特征,求解问题要分为若干步,且每一步都有几种可能的选择,而且往往在某个选择不成功时需要回头再试另外一种选择,如果到达求解目标则每一步的选择构成了问题的解,如果回头到第一步且没有新的选择则问题求解失败。

回溯法实验(n皇后问题)(迭代法)

回溯法实验(n皇后问题)(迭代法)

算法分析与设计实验报告第三次附加实验附录:完整代码(回溯法)//回溯算法递归回溯n皇后问题#include<iostream>#include<time.h>#include<iomanip>#include"math.h"using namespace std;class Queen{friend int nQueen(int); //定义友元函数,可以访问私有数据private:bool Place(int k); //判断该位置是否可用的函数void Backtrack(int t); //定义回溯函数int n; //皇后个数int *x; //当前解long sum; //当前已找到的可行方案数};int main(){int m,n;for(int i=1;i<=1;i++){cout<<"请输入皇后的个数:"; //输入皇后个数cin>>n;cout<<"皇后问题的解为:"<<endl;clock_t start,end,over; //计算程序运行时间的算法start=clock();end=clock();over=end-start;start=clock();m=nQueen(n); //调用求解的函数cout<<n<<"皇后问题共有";cout<<m<<"个不同的解!"<<endl; //输出结果end=clock();printf("The time is %6.3f",(double)(end-start-over)/CLK_TCK); //显示运行时间cout<<endl;}system("pause");return 0;}bool Queen::Place(int k)//传入行号{for(int j=1;j<k;j++){if((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k]))//如果两个在同一斜线或者在同一列上,说明冲突,该位置不可用{return false;}}return true;}void Queen::Backtrack(int t){if(t>n){sum++;/*for(int i=1;i<=n;i++) //输出皇后排列的解{cout<<x[i]<<" ";}cout<<endl;*/}else{//回溯探索第i行的每一列是否有元素满足要求for(int i=1;i<=n;i++){x[t]=i;if(Place(t)){Backtrack(t+1);}}}}int nQueen(int n){Queen X; //定义Queen类的对象X//初始化XX.n=n;X.sum=0;int *p=new int[n+1]; //动态分配for(int i=0;i<=n;i++) //初始化数组{p[i]=0;}X.x=p;X.Backtrack(1);delete[] p;return X.sum;//输出解的个数}完整代码(回溯法)//回溯算法迭代回溯n皇后问题#include<iostream>#include<time.h>#include<iomanip>#include"math.h"using namespace std;class Queen{friend int nQueen(int); //定义友元函数private:bool Place(int k); //定义位置是否可用的判断函数void Backtrack(void); //定义回溯函数int n; // 皇后个数int *x; // 当前解long sum; // 当前已找到的可行方案数};int main(){int n,m;for(int i=1;i<=1;i++){cout<<"请输入皇后的个数:";cin>>n;cout<<n<<"皇后问题的解为:"<<endl;clock_t start,end,over; //计算程序运行时间的算法start=clock();end=clock();over=end-start;start=clock();m=nQueen(n); //调用求解皇后问题的函数cout<<n<<"皇后问题共有";cout<<m<<"个不同的解!"<<endl;end=clock();printf("The time is %6.3f",(double)(end-start-over)/CLK_TCK); //显示运行时间cout<<endl;}system("pause");return 0;}bool Queen::Place(int k){for (int j=1;j<k;j++){if ((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k])) //如果两个皇后在同一斜线或者在同一列上,说明冲突,该位置不可用{return false;}}return true;}void Queen::Backtrack() //迭代法实现回溯函数{x[1] = 0;int k = 1;while(k>0){x[k] += 1; //先将皇后放在第一列的位置上while((x[k]<=n)&&!(Place(k))) //寻找能够放置皇后的位置{x[k] += 1;}if(x[k]<=n) //找到位置{if(k == n) //如果寻找结束输出结果{/*for (int i=1;i<=n;i++){cout<<x[i]<<" ";}cout<<endl; */sum++;}else//没有结束则找下一行{k++;x[k]=0;}}else//没有找到合适的位置则回溯{ k--; }}}int nQueen(int n){Queen X; //定义Queen类的对象X//初始化XX.n=n;X.sum=0;int *p=new int[n+1];for(int i=0;i<=n;i++){p[i]=0;}X.x=p;X.Backtrack();delete []p;return X.sum; //返回不同解的个数}。

回溯法解皇后问题

回溯法解皇后问题

Ch1-绪论1. 回溯法解皇后问题#include "stdio.h"#include "math.h"#include "stdlib.h"void queen(int n){ int i,j,k,jt,*q;q=malloc(n*sizeof(int));for(i=0; i<n; i++) q[i]=0;i=0; jt=1;printf("\n");printf("%d queen problem\n",n);while(jt==1){ if (q[i]<n){ k=0;while((k<i)&&((q[k]-q[i])*(fabs(q[k]-q[i])-fabs(k-i)))!=0) k=k+1;if (k<i) q[i]=q[i]+1;else{ if (i==n-1){ for(j=0; j<n; j++)printf("%5d",q[j]+1);printf("\n");q[n-1]=q[n-1]+1;}else i=i+1;}}else{ q[i]=0; i=i-1;if (i<0){ printf("\n"); free(q); return; }q[i]=q[i]+1;}}}2. 简单二分法求方程实根(1)#include "stdio.h"#include "math.h"double root(a,b,eps,f)double a,b,eps,(*f)();{ double f0,f1,c;f0=(*f)(a);while (fabs(a-b)>=eps){ c=(a+b)/2; f1=(*f)(c);if (f1==0) return(c);if (f0*f1>0) a=c;else b=c;}c=(a+b)/2;return(c);}(2)#include "root.c"main(){ double a,b,eps,f();a=1; b=2; eps=0.000001;printf("x=%7.3f\n",root(a,b,eps,f));}double f(x)double x;{ double y;y=x+log(x)-2.2;return(y);}Ch2-矩阵与线性代数方程组(1)文件头:#include "math.h"#include "stdio.h"int maqr(m,n,a,q)int m,n;double a[],q[];{ int i,j,k,l,nn,p,jj;double u,alpha,w,t;if (m<n){ printf("fail\n"); return(0);}for (i=0; i<=m-1; i++)for (j=0; j<=m-1; j++){ l=i*m+j; q[l]=0.0;if (i==j) q[l]=1.0;}nn=n;if (m==n) nn=m-1;for (k=0; k<=nn-1; k++){ u=0.0; l=k*n+k;for (i=k; i<=m-1; i++){ w=fabs(a[i*n+k]);if (w>u) u=w;}alpha=0.0;for (i=k; i<=m-1; i++){ t=a[i*n+k]/u; alpha=alpha+t*t;}if (a[l]>0.0) u=-u;alpha=u*sqrt(alpha);if (fabs(alpha)+1.0==1.0){ printf("fail\n"); return(0);}u=sqrt(2.0*alpha*(alpha-a[l]));if ((u+1.0)!=1.0){ a[l]=(a[l]-alpha)/u;for (i=k+1; i<=m-1; i++){ p=i*n+k; a[p]=a[p]/u;}for (j=0; j<=m-1; j++){ t=0.0;文件尾:for (jj=k; jj<=m-1; jj++)t=t+a[jj*n+k]*q[jj*m+j];for (i=k; i<=m-1; i++){ p=i*m+j; q[p]=q[p]-2.0*t*a[i*n+k];}}for (j=k+1; j<=n-1; j++){ t=0.0;for (jj=k; jj<=m-1; jj++)t=t+a[jj*n+k]*a[jj*n+j];for (i=k; i<=m-1; i++){ p=i*n+j; a[p]=a[p]-2.0*t*a[i*n+k];}}a[l]=alpha;for (i=k+1; i<=m-1; i++)a[i*n+k]=0.0;}}for (i=0; i<=m-2; i++)for (j=i+1; j<=m-1;j++){ p=i*m+j; l=j*m+i;t=q[p]; q[p]=q[l]; q[l]=t;}return(1);}(2)#include "stdio.h"#include "maqr.c"main(){ int i,j;static double q[4][4],a[4][3]={ {1.0,1.0,-1.0}, {2.0,1.0,0.0},{1.0,-1.0,0.0},{-1.0,2.0,1.0}};i=maqr(4,3,a,q);if (i!=0){ printf("MAT Q IS:\n");for (i=0; i<=3; i++){ for (j=0; j<=3; j++)printf("%13.7e ",q[i][j]);printf("\n");}printf("\n");printf("MAT R IS:\n");for (i=0; i<=3; i++){ for (j=0; j<=2; j++)printf("%13.7e ",a[i][j]);printf("\n");}printf("\n");}}(3)文件头:#include "stdlib.h"#include "math.h"int muav(m,n,a,u,v,eps,ka)int m,n,ka;double eps,a[],u[],v[];{ int i,j,k,l,it,ll,kk,ix,iy,mm,nn,iz,m1,ks;double d,dd,t,sm,sm1,em1,sk,ek,b,c,shh,fg[2],cs[2]; double *s,*e,*w;void ppp();void sss();s=malloc(ka*sizeof(double));e=malloc(ka*sizeof(double));w=malloc(ka*sizeof(double));it=60; k=n;if (m-1<n) k=m-1;l=m;if (n-2<m) l=n-2;if (l<0) l=0;ll=k;if (l>k) ll=l;if (ll>=1){ for (kk=1; kk<=ll; kk++){ if (kk<=k){ d=0.0;for (i=kk; i<=m; i++){ ix=(i-1)*n+kk-1; d=d+a[ix]*a[ix];}s[kk-1]=sqrt(d);if (s[kk-1]!=0.0){ ix=(kk-1)*n+kk-1;if (a[ix]!=0.0){ s[kk-1]=fabs(s[kk-1]);if (a[ix]<0.0) s[kk-1]=-s[kk-1];}for (i=文件尾:{ int i,j,p,q;double d;if (m>=n) i=n;else i=m;for (j=1; j<=i-1; j++){ a[(j-1)*n+j-1]=s[j-1];a[(j-1)*n+j]=e[j-1];}a[(i-1)*n+i-1]=s[i-1];if (m<n) a[(i-1)*n+i]=e[i-1];for (i=1; i<=n-1; i++)for (j=i+1; j<=n; j++){ p=(i-1)*n+j-1; q=(j-1)*n+i-1;d=v[p]; v[p]=v[q]; v[q]=d;}return;}static void sss(fg,cs)double cs[2],fg[2];{ double r,d;if ((fabs(fg[0])+fabs(fg[1]))==0.0){ cs[0]=1.0; cs[1]=0.0; d=0.0;} else{ d=sqrt(fg[0]*fg[0]+fg[1]*fg[1]);if (fabs(fg[0])>fabs(fg[1])){ d=fabs(d);if (fg[0]<0.0) d=-d;}if (fabs(fg[1])>=fabs(fg[0])){ d=fabs(d);if (fg[1]<0.0) d=-d;}cs[0]=fg[0]/d; cs[1]=fg[1]/d;}r=1.0;if (fabs(fg[0])>fabs(fg[1])) r=cs[1];elseif (cs[0]!=0.0) r=1.0/cs[0];fg[0]=d; fg[1]=r;return;}#include "stdio.h"#include "cgauss.c"main(){ int i;static double ar[4][4]={ {1.0,3.0,2.0,13.0},{7.0,2.0,1.0,-2.0},{9.0,15.0,3.0,-2.0},{-2.0,-2.0,11.0,5.0}};static double ai[4][4]={ {3.0,-2.0,1.0,6.0},{-2.0,7.0,5.0,8.0},{9.0,-3.0,15.0,1.0},{-2.0,-2.0,7.0,6.0}}; static double br[4]={2.0,7.0,3.0,9.0};static double bi[4]={1.0,2.0,-2.0,3.0};if (cgauss(4,ar,ai,br,bi)!=0)for (i=0;i<=3;i++)printf("b(%d)=%13.7e +j %13.7e\n",i,br[i],bi[i]); }。

回溯法求解N皇后问题

回溯法求解N皇后问题

算法的实现
• 假设回溯法要找出所有的答案结点 。 • 设(x1,x2,…,xi-1)是状态空间树中由根到一个结 点的路径,而T(x1,…xi-1)是下述所有结点xi的 集合,它使得对于每一个xi,(x1,x2,…,xi)是由 根到一个结点xi的路径;假定还存在着一些限 界函数Bi,如果路径(x1,x2,…,xi)不可能延伸到 一个答案结点,则Bi(x1,x2,…,xi)取假值,否则 取真值。 • 于是解向量X(1:n)中的第i个分量,就是那些 选自集合T (x1,x2,…,xi-1)且使Bi为真的xi
HHIT
算法8.5:n-皇后问题的解
Algorithm
Procedure NQUEENS(n) //此过程使用回溯法求出一个n*n棋盘上放置n个皇后,使其不能互相攻 击的所有可能位置// integer k,n,X(1:n) X(1)0 ; k1 // k是当前行;X(k)是当前列 // while k>0 do // 对所有的行,执行以下语句 // X(k)X(k)+1 //移到下一列// while X(k)<=n and Not PLACE(k) do //此处能放这个皇后吗// X(k)X(k)+1 //不能放则转到下一列// repeat if X(k)<=n then //找到一个位置// if k=n then print (X) //是一个完整的解则打印这个数组// else kk+1;X(k)0 //否则转到下一行// end if else kk-1 //回溯// end if repeat End NQUEENS
HHIT
Algorithm
显然,棋盘的每一行上可以而且必须摆放一个皇后, 所以,n皇后问题的可能解用一个n元向量X=(x1, x2, …, xn) 表示,其中,1≤i≤n并且1≤xi≤n,即第i个皇后放在第i行第 xi列上。 由于两个皇后不能位于同一列上,所以,解向量X必 须满足约束条件: xi≠xj (式8.1)

回溯法求解N皇后问题

回溯法求解N皇后问题

① 如果xi+1= ai+1k不是集合Si+1的最后一个元素,则令xi+1= ai+ 1k+1,即选择Si+1的下一个元素作为解向量X的第i+1个分量;
② 如果xi+1= ai+1k是集合Si+1的最后一个元素,就回溯到X=(x1, x2, …, xi),选择Si的下一个元素作为解向量X的第i个分量,假 设xi= aik,如果aik不是集合Si的最后一个元素,则令xi= aik+1; 否则,就继续回溯到X=(x1, x2, …, xi-1);
global X(1:k); integer i,k;
i1
while i<k do
if X(i)=X(k) or ABS(X(i)-X(k))=ABS(i-k) then
return (false)
end if
ii+1 repeat return (true)
判断是否有其它的皇 后与之在同一列或同 一斜对角线上
HHIT
Algorithm
(1)如果X=(x1, x2, …, xi+1)是问题的最终解,则输出这个解。 如果问题只希望得到一个解,则结束搜索,否则继续搜索其
他解;
(2)如果X=(x1, x2, …, xi+1)是问题的部分解,则继续构造解 向量的下一个分量;
(3)如果X=(x1, x2, …, xi+1)既不是问题的部分解也不是问题 的最终解,则存在下面两种情况:
while k>0 do // 对所有的行,执行以下语句 //
X(k)X(k)+1 //移到下一列//
while X(k)<=n and Not PLACE(k) do //此处能放这个皇后吗//
X(k)X(k)+1 //不能放则转到下一列//

回溯法求N皇后问题

回溯法求N皇后问题

Tree-回溯法求N皇后问题#include <stdio.h>#include <malloc.h>#define N 4 //N皇后typedef int Chessboard[N + 1][N + 1]; //第0号位置不用bool check(Chessboard cb, int i, int j) { //看棋盘cb是否满足合法布局int h, k;int m = i + j, n = i - j;for(h=1; h<i; h++) {if(cb[h][j] == 1 && h != i) return false; //检查第j列if(m-h<=N && cb[h][m-h] == 1 && h != i) return false; //检查斜的,m-h<=N是为了保证不越界if(h-n<=N && cb[h][h-n] == 1 && h != i) return false; //检查斜的,h-n<=N是为了保证不越界}for(k=1; k<N; k++)/*检查第i行的*/ if(cb[i][k] == 1 && k != j) return false;return true;}void printfChessboard(Chessboard cb) {//打印棋盘int i, j;for(i=1; i<=N; i++) {for(j=1; j<=N; j++) printf("%d ", cb[i][j]);printf("\n");}printf("\n");}/*进入本函数时,在n*n棋盘前n-1行已放置了互不攻击的i-1个棋子。

现从第i行起继续为后续棋子选择合适位置。

回溯典型题目——N皇后问题剖析

回溯典型题目——N皇后问题剖析

N皇后问题问题描述:在N*N的方格中放置N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上)对于给定的N,输出摆放方案并求出有多少种合法的放置方法。

【假设N<=10】基础:四皇后问题我们先来看看四皇后问题,在一个4*4的棋盘中摆放4个皇后,四个皇后不能摆在互相攻击的位置。

方案一:回溯法(程序中包含递归和深搜)源代码://四皇后问题:回溯#include <stdio.h>#include <string>int flag[4][4]; //用于标记放过的棋子//n个皇后,深搜int count=0;int iscorrect(int i,int j){ //判断是否可以放置棋子int a,b;for(a=i,b=0;b<4;b++){if(flag[a][b]==1) //说明在同一行有棋子return 0;}for(a=0,b=j;a<4;a++){if(flag[a][b]==1) //说明在同一行有棋子return 0;}for(a=i-1,b=j-1;a>=0&&b>=0;a--,b--){ //左上方if(flag[a][b]==1)return 0;}for(a=i-1,b=j+1;a>=0&&b<=3;a--,b++){ //左下方if(flag[a][b]==1)return 0;}for(a=i+1,b=j-1;a<=3&&b>=0;a++,b--){ //右上方if(flag[a][b]==1)return 0;}for(a=i+1,b=j+1;a<=3&&b<=3;a++,b++){ //判断右下方if(flag[a][b]==1)return 0;}return 1;}void DFSQ(int i){int m,n;int j;//i代表行数,j代表列数if(i==4){ //因为棋盘是(n-1)*(n-1)模式的,而i是行,当棋盘到第四行的时候,表明已//经完成0~3的所有排布已经完成for(m=0;m<4;m++){for(n=0;n<4;n++){printf("%d ",flag[m][n]);}printf("\n");}count++;printf("\n");return; //不要忘记这个}else{for(j=0;j<4;j++){if(iscorrect(i,j)){ //如果可以放置棋子flag[i][j]=1; //标记flag[i][j]DFSQ(i+1); //递归调用flag[i][j]=0; //消除标记}}}}int main(){memset(flag,0,sizeof(flag));DFSQ(0);printf("count=%d\n",count);return 0;}其实从四皇后问题拓展到n皇后问题是非常简单的事情,方案一进阶到N皇后的源代码:N皇后其实只要把其中的4改成N就行了:源代码:#include <stdio.h>#include <string>int flag[10][10]; //用于标记放过的棋子int number; //表示棋子个数//n个皇后,深搜int count=0;int iscorrect(int i,int j){ //判断是否可以放置棋子int a,b;for(a=i,b=0;b<number;b++){if(flag[a][b]==1) //说明在同一行有棋子return 0;}for(a=0,b=j;a<number;a++){if(flag[a][b]==1) //说明在同一行有棋子return 0;}for(a=i-1,b=j-1;a>=0&&b>=0;a--,b--){ //左上方if(flag[a][b]==1)return 0;}for(a=i-1,b=j+1;a>=0&&b<=number-1;a--,b++){ //左下方if(flag[a][b]==1)return 0;}for(a=i+1,b=j-1;a<=number-1&&b>=0;a++,b--){ //右上方if(flag[a][b]==1)return 0;}for(a=i+1,b=j+1;a<=number-1&&b<=number-1;a++,b++){ //判断右下方if(flag[a][b]==1)return 0;}return 1;}void DFSQ(int i){int m,n;int j;//i代表行数,j代表列数if(i==number){ //因为棋盘是(n-1)*(n-1)模式的,而i是行,当棋盘到第四行的时候,表明已经完成0~number-1的所有排布已经完成for(m=0;m<number;m++){for(n=0;n<number;n++){printf("%d ",flag[m][n]);}printf("\n");}count++;printf("\n");return; //不要忘记这个}else{for(j=0;j<number;j++){if(iscorrect(i,j)){ //如果可以放置棋子flag[i][j]=1; //标记flag[i][j]DFSQ(i+1); //递归调用flag[i][j]=0; //消除标记}}}}int main(){scanf("%d",&number);memset(flag,0,sizeof(flag));DFSQ(0);printf("count=%d\n",count);return 0;}。

n皇后问题

n皇后问题

n 后问题1 问题描述:N 皇后问题是一个古老而著名的问题。

该问题是十九世纪著名的数学家高斯1850年提出的。

八皇后问题要求在一个N *N 的棋盘上放上N 个皇后,使得每一个皇后既攻击不到另外N-1个皇后,也不被另外N-1个皇后所攻击.按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子,问有多少种不同的摆法?并找出所有的摆法。

因此,N 皇后问题等于要求N 个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。

2 回朔法回溯法有“通用的题解法”之称。

从问题的某种可能情况出发,搜索所有能到达的可能情况,然后以其中一种可能的情况为新的出发点,继续向下探索,当所有可能情况1 2 3 4 5 6 7 8 1 2 3 4 5 6 78都探索过且都无法到达目标的时候,再回退到上一个出发点,继续探索另一个可能情况,这种不断回头寻找目标的方法称为“回溯法”。

适用于解组合是较大的问题。

回朔法思想:1针对所给问题,定义问题的解空间。

2.确定易于搜索的解空间结构。

3.以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索。

在搜索过程中,通常采用两种策略避免无效搜索:一是用约束函数剪去得不到可行解的子树;二是用限界函数剪去得不到最优解的子树。

这两类函数统称为剪枝函数。

回溯算法的一个显著的特性是在搜索过程中动态产生问题的解空间。

在任何时刻,只保存从根结点到当前扩展结点的路径。

因此,回溯算法的空间需求为o(n),(n为从根结点起最长路径的长度)。

而显式地存储整个解空间则需要o(2n)或o(n!)内存空间。

回溯法对解空间作深度优先搜索,因此,在一般情况下用递归方法实现回溯法。

void backtrack (int t){if (t>n) output(x);elsefor (int i=f(n,t);i<=g(n,t);i++){x[t]=h(i);if (constraint(t)&&bound(t)) backtrack(t+1);}}采用树的非递归深度优先遍历算法,可将回溯法表示为一个非递归迭代过程。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

回溯法之N皇后问题(C语言)
#include<stdio、h>#include<stdlib、h> int
n,stack[100]; //存当前路径int total; //路径数 void
make(int l)
//递归搜索以stack[l]为初结点的所有路径{ int i,j; //子结点个数 if (l==n+1)
{ total=total+1; //路径数+1 for(i=1;i<=n;i++)
printf("%-3d",stack[i]); //输出第i行皇后的列位置stack[i] printf("\n"); exit; //回溯(若试题仅要求一条路径,则exit改为halt即可) } for (i=1;i<=n;i++) { stack[l]=i; //算符i作用于生成stack[l-1]产生子状态stack[l]; if (!att(l,i))
make(l+1); } //再无算符可用,回溯 } int att(int l,int i){ int k; for (k=1;k<l;k++)
if (abs(l-k)==abs(stack[k]-i)||i==stack[k])
return1; return 0; }int main(){ printf("N=");
scanf("%d",&n); total=0; //路径数初始化为0 make(1); //从结点1出发,递归搜索所有的路径 printf("%d\n",total); system("pause"); return 0;} 由回溯法的算法流程可以看出,除非边界条件设置不当而导致死循环外,回溯法一般是不会产生
内存溢出的。

但是,回溯法亦有其致命的弱点时间效率比数学解析法低。

为了改善其时效,我们可以从下述几个方面考虑优化:
1、递归时对尚待搜索的信息进行预处理,减少搜索量;
2、尽可能减少分支(解答树的次数);
3、增加约束条件,使其在保证出解的前提下尽可能“苛刻”;
4、在约束条件中设置限定搜索层次的槛值。

相关文档
最新文档