- 1、本文档共6页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
算法分析第三次实验报告
武汉工业学院
《计算机算法设计与分析》
实验三:回溯法解决n后问题
姓 名:巩玲玉
专 业:网络工程
班 级:1002班
学 号:100511108
学 院:数学与计算机学院
指导教师:夏祥胜
2012 年 11月26日
n后问题
问题描述
n后问题要求在一个n×n格的棋盘上放置n个皇后,使得他们彼此不受攻击。按照国际象棋的规则,一个皇后可以攻击与之处在同一行或者同一列或者同一斜线的其他任何棋子。因此,n后问题等价于要求在n×n格的棋盘上放置n个皇后,使得任何2个皇后不能被放在同一行或者同一列或者同一斜线上。
皇后的攻击范围包括:
1).同一行
2).同一列
3).同一对角线(包括两个方向)
分析后可见,皇后之间互不攻击当且仅当满足下列条件:
1).每一行只能有一个皇后
2).每一列只能有一个皇后
3).任意条对角线上面只能有一个皇后
算法设计
于n后问题,我们用n元组x[1:n]表示它的解。其中,x[i]表示皇后i放在棋盘的第i行的第x[i]列。由于不允许将任何2个皇后放在同一列上,所以解向量中的诸x[i]互不相同。在这里,任何2个皇后不能放在同一斜线上的问题是隐约束。对于一般的n后问题,这一隐约束条件可以化成显约束的形式。如果将n×n格的棋盘看成一个二维方阵,其行号从上到下。列号从左到右依次编号为1,2,… ,n,那么,从左上角到右下角的主对角线及其平行线(即斜率为-1的各斜线)上,元素的2个下标值的差(行号-列号)值相等。同理,斜率为+1的每一条斜线上,元素的2个下标值的和(行号+列号)值相等。因此,若2个皇后放置的位置分别是(i, j)和(k, l)– j = k – l 或 i + j = k + l,则说明这2个皇后处于同一斜线上。以上2个方程分别等价于i – k = j – l或k – i = l – j。由此可知,只要|i – k| = |j – l|成立,就表明这2个皇后位于同一条斜线上。于是,问题的隐约束化成了显约束。据此,我们可以设计一个函数Place来测试若将皇后K放在x[k]列是否与前面放置的k-1个皇后都不在同一列,而且都不在同一斜线上。
用回溯法解n后问题时,可以用一棵完全n叉树来表示其解空间。用可行性约束函数Place可剪去不满足行、列和斜线约束的子树。
在下面所给出的解n后问题的回溯描述中,递归函数Backtrack(1)实现对整个解空间的回溯搜索。Backtrack(i)搜索解空间中第i层子树。函数Backtrack类Queen的成员。在算法queen中,当in时,算法搜索到叶子结点,得到一个新的n皇后互不攻击放置方案,当前已找到的可行方案数sum加1.当in时,当前扩展结点Z是解空间中的内部结点。该结点有x[i]=1.2,…,n,共n个儿子结点。对当前扩展结点Z的每一个儿子结点,由place检查其可行性,并以深度优先的方式递归地对可行子树搜索,或剪去不可行子树。
解n后问题的回溯算法可描述如下:
class Queen{
friend int nQueen(int);
private:
bool Place(int k);
void Backtrack(int t);
int n,//皇后个数
*x;//当前解
long sum;//当前已经找到的可行的方案数
}
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++;
else
for(int i = 1; i n; i++){
x[t] = i;
if(Place(t))
Backtrack(t + 1);
}
}
int nQueen(int n)
{
Queen X;//初始化X
X.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;
}
完整程序如下:
#includeiostream
#includemath.h
#includetime.h
using namespa
文档评论(0)