算法分析与设计上机报告 完整版Word文档下载推荐.docx
《算法分析与设计上机报告 完整版Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《算法分析与设计上机报告 完整版Word文档下载推荐.docx(18页珍藏版)》请在冰豆网上搜索。
张璐(201224020102)
刘天聪(201224020126)
成果的测试,发现存在的问题
目录
1、问题描述·
·
第1页
2、算法分析·
第2页
3、伪代码·
第5页
4、设计流程·
第6页
5、演示程序设计·
第8页
6、测试与结论·
第16页
7、设计过程遇到的问题、思考及解决方法·
第17页
八、总结·
1、问题描述
八皇后问题是一个古老而著名的问题,它是回溯算法的典型例题。
该问题是十九世纪德国著名数学家高斯于1850年提出的:
在8行8列的国际象棋棋盘上摆放着八个皇后。
使他们之间不能互相攻击。
若两个皇后位于同一行、同一列或同一对角线上,则它们之间就可以互相攻击。
后来人们从8皇后问题延伸到了n皇后问题,问题的重点即使每两个皇后都不能在同一行、同一列、同一对角线上。
在分析这个问题时,我们不妨从第一列开始放置皇后。
这里我们选择使用回溯法即经典的递归法来求解n皇后问题,这个算法将在棋盘上一列一列地放置皇后直到n个皇后在不相互攻击的情况下都被摆放在棋盘上,算法便终止。
当一个新加入的皇后因为与已经存在的皇后之间相互攻击而不能被摆在棋盘上时,算法便发生回溯。
一旦发生这种情况,就试图把最后放在棋盘上的皇后移动到其他地方。
这样做是为了让新加入的皇后能够在不与其它皇后相互攻击的情况下被摆放在棋盘的适当位置上。
这是一个组合优化问题,在n×
n格的棋盘上放置彼此不受攻击的n个皇后。
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n后问题等价于再n×
n的棋盘上放置n个皇后,任何2个皇后不妨在同一行或同一列或同一斜线上。
输入:
给定棋盘的大小n(n≤13)
输出:
输出有多少种放置方法。
要解决n皇后问题,其实就是要解决好怎么放置这n个皇后,每一个皇后与前面的所有皇后不能在同一行、同一列、同一对角线,在这里我们可以以行优先,就是说皇后的行号按顺序递增,只考虑第i个皇后放置在第i行的哪一列,所以在放置第i个皇后的时候,可以从第1列判断起,如果可以放置在第1个位置,则跳到下一行放置下一个皇后。
如果不能,则跳到下一列...直到最后一列,如果最后一列也不能放置,则说明此时放置方法出错,则回到上一个皇后向之前放置的下一列重新放置。
此即是回溯法的精髓所在。
当第n个皇后放置成功后,即得到一个可行解,此时再回到上一个皇后重新放置寻找下一个可行解...如此后,即可找出一个n皇后问题的所有可行解。
二、算法分析
以8皇后为例。
我们给棋盘上的行和列从1到8编号,同时也给皇后从1到8编号。
由于每一个皇后应放在不同的行上,不失一般性,假设皇后i放在第i行上,因此8皇后问题可以表示成8元组(X1,X2,…,Xn),其中,X(i=1,2,…,8)表示皇后i所放置的列数。
这种表示法的显式约束条件是S={1,2,3,4,5,6,7,8},
i=1,2,…,8。
在这种情况下,解空间由8个8元组组成,而隐式约束条件是没有两个X相同(即所有皇后在不同列上),且满足不存在两个皇后在同一对角线上。
加上隐式约束条件,问题的解空间可进一步减小。
此时,解空间大小为8!
,因为所有解都是8元组的一个置换。
下图表示了8皇后问题的一个解
X=(4,6,8,2,7,1,3,5)
我们可以用一棵树表示8皇后问题的解空间。
由于8皇后问题的解空间为8!
种排列,因此我们将要构造的这棵树实际上是一棵排列数。
为了简单起见,下图只给出了n=4时问题的一种可能树结构。
这棵树有24个叶子结点,树中结点按照深度优先搜索编号,树中的边表示X可能取的值。
假设树的根为第1层,树中第1层到第2层的边上的数字表示X可能取的值。
最左边的子树包含X=1的所有解,最左子树的左子树X=1的所有解。
第i层到第i+1层的边上的数字表示X可能取的值。
因此,从根结点到叶子结点的所有路径定义了问题的解空间。
树中的每一个结点确定所求问题的一个问题状态。
从根结点到其他结点的所有路径确定了问题的状态空间。
从根结点到叶子结点的所有路径定义了问题的解空间,我们称解空间中那些满足约束条件的状态为答案状态。
解空间的树结构称为状态空间树。
结点31为答案状态,对应的解为(2,4,1,3)。
在4皇后解空间的树结构中,在每个内部结点处,将问题的解空间分为互不相交的子集。
例如,在结点1处,解空间被分成四个不相交的集合,即分别以结点2,18,34,和50为根的子树。
在结点18处,X=2,这棵子树所表示的子解空间进一步被分成三个互不相同的子集。
对于给定的问题,一旦设想出它的一种状态空间树,就可以按照一定的方式生成问题的状态,并确定问题的答案状态。
有两种生成问题状态空间的方法,这两种方法都是从根节点开始生成其他结点。
如果一个结点已经生成子结点,而它的所有子结点还未全部生成,则称这个结点为活结点,称当前正在生成其子结点的活结点为扩展结点或E结点,不再进一步扩展子结点或者其子结点已全部生成的结点为死结点。
在这两种方法中,都要保留一个活结点表。
在第一种方法中,一旦当前的E结点A生成一个子结点B,就将该子结点B变成活结点,当检查完子树B之后,A结点再次成为E结点。
这就是深度优先生成结点。
在第二种方法中,一个E结点一直保持到变成死结点为止。
在这两种方法中,将用界限函数杀死那些还没有全部生成子结点的活结点。
需要仔细考虑限界函数的设计,使得算法结束时存在答案结点。
有时还有根据题意,使设计的限界函数能够生产问题的所有解。
使用限界函数的深度优先生成结点的方法称为回溯法。
E结点一直保持到死为止的状态空间生成结点的方法叫分枝限界法。
我们可以很容易地将8皇后问题推广的n皇后问题(n-queenproblem),即找到n×
n的棋盘上放置n个皇后并使其不能相互攻击的所有解。
设X=(x1,x2,…,xn)表示问题的解,其中xi表示第i个皇后放在第i行所在的列数。
由于不存在两个皇后位于同一列上,因此xi互不相同。
设有两个皇后分别位于棋盘(i,j)和(k,l)处,如果两个皇后位于同一对角线上,则表明它们所在的位置应该满足:
i-j=k-l或i+j=k+l。
综合这两个等式可得,如果两个皇后位于同一对角线上,那么它们的位置关系一定满足|j-l|=|i-k|。
下面的算法N-QUEEN给出n皇后问题的所有解。
N-QUEEN(n)
1x[1]<
-0
2k<
-1
3whilek>
0do
4x[k]<
-x[k]+1
5whilex[k]<
=n&
notPLACE(k)do
6x[k]<
7ifx[k]<
=n
8thenifk=n
9thenoutput(X)
10elsek<
-k+1
11x[k]<
-0
12elsek<
-k-1
13return
第1~2行进行初始化。
第3行的while循环表示对所有行执行循环体,计算xk值。
在第5~6行的while循环中,对于每一个xk值,调用PLACE过程测试它的合法性,即寻找满足约束条件的xk值。
第7行中,如果找到一个放置问题,则进一步测试所求(x1,x2,…,xk)是否为问题的解,这只需判断k是否等于n即可。
如果是问题的解,则输出(第9行),否则通过赋值语句将k值增加1,继续外层while循环。
如果第7行的条件为假,则表明不存在合法的xk值,此时将k值减1(第12行),进行回溯。
PLACE过程如下:
PLACE(k)
1i<
2whilei<
kdo
3if(x[i]=x[k]orabs(x[i]-x[k])=abs(i-k))
4thenreturn(false)
5i<
-i+1
6return(true)
PLACE过程检查到目前为止的第k个皇后所在的列数xk,是否与前k-1个皇后所在列xi(1<
=i<
=k-1)在同一列或在同一对角线上(第3行)。
如果这些条件都不违反,则返回true,否则返回false。
3、伪代码
1、算法N-QUEEN给出n皇后问题的所有解
N-QUEEN(n)
1x[1]<
-0//第1个皇后的列位置初始化
2k<
-1//当前行
3whilek>
4x[k]<
-x[k]+1//到下一行
5whilex[k]<
notPLACE(k)do//尚未出棋盘,而且位置不合法
6x[k]<
7ifx[k]<
=n//找到一个位置
8thenifk=n//检测是否为问题的解
9thenoutput(X)//输出解
10elsek<
-k+1//转下一行,即给下一个皇后找位置
11x[k]<
-0//初始化当前皇后列取值
12elsek<
-k-1//回溯
13return
2、PLACE程序测试它的合法性
kdo//从第一行开始逐行试
3if(x[i]=x[k]orabs(x[i]-x[k])=abs(i-k))//同一行或同一对角线有两个皇后
四、设计流程
1打开visual
studio新建一个MFCAPPwizrd(exe)工程,
2按如图为窗体放置相应的组件,将窗体的名称改成“皇后问题”并按以下表格设置好相关的ID和属性
3
标题
ID
属性
分组框
开始
IDC_START
暂停/单步
IDC_PAUSE
n值
IDC_BOARD_SIZE
单步
IDC_STEP_BY
不中断
IDC_NO_INT
继续
IDC_CONTINUE
停止
IDC_STOP
Queen_panel
IDC_QUEEN_PANEL
关于
IDC_ABOUT
按Ctrl+W为IDC_QUEEN_PANEL添加一个Type为QueenPanel的成员变量m_panel
4为组件画板新建一个名为QueenPanel的类,并添加以下成员:
public
private
QueenPanel();
voidDrawBoard(CDC*pDC,intsize,intcell);
Que