博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
经典回溯问题——八皇后问题
阅读量:6926 次
发布时间:2019-06-27

本文共 1898 字,大约阅读时间需要 6 分钟。

算法提出:

在国际象棋棋盘上(8*8)放置八个皇后,使得任意两个皇后之间不能在同一行,同一列,也不能位于同于对角线上。问共有多少种不同的方法,并且指出各种不同的放法。

算法思路:

  首先我们分析一下问题的解,我们每取出一个皇后,放入一行,共有八种不同的放法,然后再放第二个皇后,同样如果不考虑规则,还是有八种放法。于是我们可以用一个八叉树来描述这个过程。从根节点开始,树每增加一层,便是多放一个皇后,直到第8层(根节点为0层),最后得到一个完全八叉树。  

  紧接着我们开始用深度优先遍历这个八叉树,在遍历的过程中,进行相应的条件的判断。以便去掉不合规则的子树。

  那么具体用什么条件来进行子树的裁剪呢?

  我们先对问题解的结构做一个约定。

  用X[i]来表示,在第i行,皇后放在了X[i]这个位置。

  于是我们考虑第一个条件,不能再同一行,同一列于是我们得到x[i]不能相同。剩下一个条件是不能位于对角线上,这个条件不是很明显,我们经过分析得到,设两个不同的皇后分别在j,k行上,x[j],x[k]分别表示在j,k行的那一列上。那么不在同一对角线的条件可以写为abs((j-k))!=abs(x[j]-x[k]),其中abs为求绝对值的函数。

  于是下面我们便可以利用一个递归的调用来遍历八叉树。

  我们首先定义一个访问某节点所有子节点的函数

 
void backtrack(int t){    if(t>num) //num为皇后的数目    {        sum++;//sum为所有的可行的解        for(int m = 1;m
 

下面我们定义了条件判断函数

 
bool place(int k){    for(int j = 1;j
 

上面的函数便是按照我们上面说介绍的条件进行判断。

最后就是主程序的调用了

static int num;static int *x;static int sum;void main(){    num = 8;    sum = 0;    x = new int[num+1];    for(int i= 0;i<=num;i++)        x[i] = 0;    backtrack(1);    cout<<"方案共有"<

一个更加简便的解法:

  使用1 - 8的全排列进行依次判断,判断只需要考虑每种排列的斜线是否会被攻击!

bool isPass(int*);int EightQueue() {	int a[8] = { 0,1, 2, 3, 4, 5, 6, 7 };	int n = 0;		while (next_permutation(a, a + 8)) {//一一判断排列是否可行		if (isPass(a))++n;//可行就计数一次	}	return n;}bool isPass(int *a) {//判断斜方是否会受到其他皇后的攻击	int queue[8][8] = { 0 };	for(int i=0;i<8;++i)		queue[i][a[i]] = 1;//按照0-7数字,每行按照a中数字对应其列进行放置皇后,则不会出现同行同列出现两个皇后了,大大减少了判断	for (int i = 0; i < 8; ++i) {		for (int t = i - 1, k = a[i] - 1; t >= 0 && k >= 0; --t, --k) {//左上方			if (queue[t][k] == 1)				return false;		}		for (int t = i + 1, k = a[i] + 1; t < 8 && k < 8; ++t, ++k) {//右下方			if (queue[t][k] == 1)				return false;		}		for (int t = i + 1, k = a[i] - 1; t < 8 && k >= 0; ++t, --k) {//左下方			if (queue[t][k] == 1)				return false;		}		for (int t = i - 1, k = a[i] + 1; t >= 0 && k < 8; --t, ++k) {//右上方			if (queue[t][k] == 1)				return false;		}	}	return true;}

  

转载于:https://www.cnblogs.com/zzw1024/p/10539432.html

你可能感兴趣的文章
Linux下Socket 函数集(二)
查看>>
漫谈程序员系列:受刺激啦,开篇啦
查看>>
特效编辑器开发手记1——令人蛋疼菊紧的Cocos2d-x动态改变粒子数
查看>>
Java源码分析系列之ArrayList读后感
查看>>
安卓中的消息循环机制Handler及Looper详解
查看>>
练习命令
查看>>
转 fiddler常见的应用场景
查看>>
android开发学习 ------- 仿QQ侧滑效果的实现
查看>>
139.00.007 Git学习-Cheat Sheet
查看>>
js的基本数据类型有哪些?
查看>>
html 5 新增标签及简介
查看>>
c#多线程中Lock()关键字的用法小结
查看>>
征服恐惧!用 Vim 写 iOS App
查看>>
Struts_登录练习(配置拦截器)
查看>>
ASP.NET Core 2.0 使用支付宝PC网站支付
查看>>
centos7安装mha4mysql
查看>>
Android ListView和ListAdapter(附电话簿实例)
查看>>
Linux磁盘管理之LVM详解
查看>>
我的友情链接
查看>>
关于通达Oa的一些问题,raid,论坛
查看>>