回溯法及其应用

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

八皇后问题的基本策略及其应用

郭洋洋王刚李晴孙佳

(陕西师范大学计算机科学学院09级计算机科学与技术,西安,710062)

摘要:针对八皇后问题,本文采用回溯法,给出递归与非递归两种算法的设计与分析,并通过实验验证两种算法的性能,得出最佳的算法。

关键词:八皇后;回溯法;递归算法;非递归算法

The Basic Algorithm Strategy For Eight Queens

And Its Application

Guo Yangyang,Wang Gang,Li Qing, Sun Jia

(School of Computer Science ,Shanxi Normal University ,Xi’an ,710062 )

Abstract: Aiming at the problem of Eight Queens,this paper gives Backtracking , and Recursive algorithm and Non-recursive algorithm , and show the design and analysis of the two kinds of algorithms,and through the experiment ,verified the performance of them,getting the most suitable algorithm.

Keywords: Eight Queens; Backtracking; Recursive; Non-Recursive

1 引言

八皇后问题由19 世纪著名的数学家高斯在1850 年提出:在8 ×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法.

回溯算法是尝试搜索算法中最为基本的一种算法,其采用了一种“走不通就调头”的思想,作为其控制结构[1]。回溯法在用来求问题的所有解时,要回溯到根,且根节点的所有可行的子树都已被搜索遍才结束。而回溯法在用来求解问题任一解时,只要搜索到问题的一个解就可以结束。这就是以深度优先的方式系统的搜索问题解的回溯法,它适用于解决一些类似n皇后问题等就切方案问题,也可以解决一些最优化问题。

2 问题描述与模型

八皇后问题:在8 ×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法.

例如图一所示:

图一 8皇后问题

模型建立:不妨设8个皇后为x i ,她们分别在第i行(i=1,2,3,…,8),这样问题的解空间,就是一个8皇后所在列的序号,为n元一维向量(x1,x2,x3,x4,x5,x6,x7,x8),搜索空间是1≤x i≤8(i=1,2,3,…,8),共88个状态。约束条件是8个点(1,x1),(2,x2),(3,x3),(4,x4),(5,x5),(6,x6),(7,x7),(8,x8),不在同一列和同一对角线上。

3 算法设计

下面通过枚举法、非递归算法、递归算法来求解问题。

3.1 枚举法

算法设计:

运用枚举法解决此问题是通过八重循环,按照深度优先思想,从第一个皇后开始搜索,确定第一个位置后,在搜索第二个位置;……;每进一步检查是否满足约束条件,不满足时,用continue回溯到上一个皇后继续寻找;满足约束条件时,开始下一个皇后的搜索;直到找出问题的解。

显然,问题的搜索空间有88个状态。约束条件有有三个[1]:

(Ⅰ)不在同一列的表达式为:x i≠x j

(Ⅱ)不在同一主对角线上的表达式为:x i-i≠x j-j;

(Ⅲ)不在同一负对角线上的表达式为:x i+i≠x j+j;

以上条件和可以合并为一个“不在同一对角线上”的约束条件,表达式为:

abs(x i-x j)≠abs(i-j)(abs()取绝对值)。

算法伪代码如下:

main()

{

for ( a[1]=1; a[1]<=8;a[1]=a[1]+1)

for(a[2]=1;a[2]<=8;a[2]=a[2]+1)

{if (check(a,2)= =0) continue;

for (a[3]=1;a[3]<=8;a[3]=a[3]+1)

{if (check(a,3)= =0) continue;

for (a[4]=1;a[4]<=8;a[4]=a[4]+1)

{ if (check(a,4)= =0) continue;

for (a[5]=1;a[5]<=8;a[5]=a[5]+1)

{if (check(a,5)= =0) continue;

for (a[6]=1;a[6]<=8;a[6]=a[6]+1)

{if (check(a,6)= =0) continue;

for (a[7]=1;a[7]<=8;a[7]=a[7]+1)

{if (check(a,7)= =0) continue;

for (a[8]=1;a[8]<=8;a[8]=a[8]+1)

{if (check(a,8)= =0) continue;

else

for (int i=1;i<=8;i++)

printf (a[i]);

}}}}}}}}

check( a,i) 功能:

将第i个皇后和前i-1个皇后比较,如果满足上述三个约束条件,则继续寻找第i+1个皇后的位置;否则,继续查找第i个皇后;若找不到则返回0;否则返回1.

算法分析1:

表面上看,这个算法的时间复杂度为88,其实算法在check()函数返回0时,continue 返回,便不再执行其后的皇后查找工作,所以其时间复杂度并没有88。

当然,我们可以将算法稍微改变后,它的复杂度便立即为88。在算法中:

将前七个“if (check(a[],i)==0) continue;”去掉,只留下最后一个,同时将check 函数改为如下:

_check(a[],n)

{

int i,j;

for (i=2;i<=n;i++)

for (j=1;j

if((abs(a[i]-a[j])==abs(i-j))||(a[i]=a[j]))

return 0;

return 1;

}

此时算法退化为完全的盲目搜索,算法的复杂性就是88。

3.2 非递归算法

虽然枚举法有很好的可读性,从continue也可以看出回溯算法的思想,可是她只能解决常量个皇后的问题,不能解决任意个n个皇后的问题,因此也不是典型的回溯法模型。

下面的非递归算法是典型的回溯算法模型。

非递归算法框架:

int a[n];

int i;

初始化数组a[];

i=1;

while(i>0(有路可走)and([未达到目标]))

{

if(i>n)

相关文档
最新文档