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

本文共 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

你可能感兴趣的文章
Nginx负载均衡Tomcat、Resin实现动静分离
查看>>
马哥预习,第二天,基础命令学习
查看>>
聊聊spring jdbc的RowMapper
查看>>
[Java代码] Java实现直接插入排序和折半插入排序算法示例
查看>>
PPP中的pap和chap认证
查看>>
nginx服务器的内核优化配置
查看>>
Netgear wndr3700v2 路由器刷OpenWrt打造全能服务器(十二)恢复
查看>>
如何实现在虚拟机上的Linux系统上安装vmware tools
查看>>
机械硬盘显示无法访问磁盘结构损坏且无法读取,里面的文件怎样找到
查看>>
开启博客的第一篇
查看>>
Exchange2007-Exchange2010升级-06 数据库高可用组的创建
查看>>
phpHiveAdmin是如何通过Hive/Hadoop工作的
查看>>
[翻译完成] 树莓派搭建Google TV
查看>>
双向链表内结点的删除(4)
查看>>
项目总结
查看>>
JSON字符串转成对象
查看>>
云端对决,新旧势力的PK赛
查看>>
SaltStack 中ZMQ升级
查看>>
grep,egrep使用以及正则表达式的使用
查看>>
在java实现redis缓存技术的基本操作
查看>>