八皇后问题

一、题意解析

  国际象棋中的皇后,可以横向、纵向、斜向移动。如何在一个8X8的棋盘上放置8个皇后,使得任意两个皇后都不在同一条横线、竖线、斜线方向上?八皇后问题是一个古老的问题,于1848年由一位国际象棋棋手提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,如何求解?以高斯为代表的许多数学家先后研究过这个问题。后来,当计算机问世,通过计算机程序的运算可以轻松解出这个问题。

二、如何解决八皇后问题?

  所谓递归回溯,本质上是一种枚举法。这种方法从棋盘的第一行开始尝试摆放第一个皇后,摆放成功后,递归一层,再遵循规则在棋盘第二行来摆放第二个皇后。如果当前位置无法摆放,则向右移动一格再次尝试,如果摆放成功,则继续递归一层,摆放第三个皇后......

  如果某一层看遍了所有格子,都无法成功摆放,则回溯到上一个皇后,让上一个皇后右移一格,再进行递归。如果八个皇后都摆放完毕且符合规则,那么就得到了其中一种正确的解法。说起来有些抽象,我们来看一看递归回溯的详细过程。

  1.第一层递归,尝试在第一行摆放第一个皇后

  2.第二层递归,尝试在第二行摆放第二个皇后(前两格被第一个皇后封锁,只能落在第三格):

  3.第三层递归,尝试在第三行摆放第三个皇后(前四格被第一第二个皇后封锁,只能落在第五格):

  4.第四层递归,尝试在第四行摆放第四个皇后(第一格被第二个皇后封锁,只能落在第二格):

  5.第五层递归,尝试在第五行摆放第五个皇后(前三格被前面的皇后封锁,只能落在第四格):

  6.由于所有格子都“绿了”,第六行已经没办法摆放皇后,于是进行回溯,重新摆放第五个皇后第八格。:

  7.第六行仍然没有办法摆放皇后,第五行也已经尝试遍了,于是回溯到第四行,重新摆放第四个皇后第七格。:

  8.继续摆放第五个皇后,以此类推......

三、八皇后问题的代码实现

  解决八皇后问题,可以分为两个层面:

1.找出第一种正确摆放方式,也就是深度优先遍历。

2.找出全部的正确摆放方式,也就是广度优先遍历。

我们本篇只介绍如何找出第一种正确摆放方式。具体代码如下:

 //"八皇后问题回溯实现"
#include <iostream>
using namespace std;
const int ArSize = ;//这个数等于几,就是几皇后。
int num = ;
void solve(bool arr[ArSize][ArSize], int row);
bool check(bool arr[ArSize][ArSize], int row, int column);
void outPut(bool arr[ArSize][ArSize]); int main()
{
bool chessboard[ArSize][ArSize];
// 数组初始化
for (auto &i : chessboard)
{
for (auto &j : i)
{
j = false;
}
}
solve(chessboard, );
cout << "八皇后问题共有" << num << "种解!" << endl;
system("pause");
return ;
}
// 回溯法
void solve(bool arr[ArSize][ArSize], int row)
{
for (int column = ; column < ArSize; ++column)
{
arr[row][column] = true;
if (check(arr, row, column))
{
if (row + == ArSize)
{
outPut(arr);
}
else
{
solve(arr, row + );
}
}
arr[row][column] = false;
}
}
// 判断皇后的落点是否合规
bool check(bool arr[ArSize][ArSize], int row, int column)
{
if (row == )
{
return true;
}
int i, j;
// 判断纵向是否有冲突
for (i = ; i < row; ++i)
{
if (arr[i][column])
{
return false;
}
}
i = row - ;
j = column - ;
// 判断正斜对角线是否有冲突
while (i >= && j >= )
{
if (arr[i][j])
{
return false;
}
--i;
--j;
}
i = row - ;
j = column + ;
// 判断负斜对角线是否有冲突
while (i >= && j <= ArSize - )
{
if (arr[i][j])
{
return false;
}
--i;
++j;
}
return true;
}
// 打印每种正确的解法
void outPut(bool arr[ArSize][ArSize])
{
++num;
cout << "**********************" << num << "*********************" << endl;
for (int i = ; i < ArSize; ++i)
{
for (int j = ; j < ArSize; ++j)
{
cout << arr[i][j] << " ";
}
cout << endl;
}
cout << "*********************************************" << endl;
}

  输出结果的部分截图如下:

参考资料:

http://www.cnblogs.com/yonggandefeng/p/6275861.html

一道算法题-八皇后问题(C++实现)的更多相关文章

  1. 每天一道算法题(4)——O(1)时间内删除链表节点

    1.思路 假设链表......---A--B--C--D....,要删除B.一般的做法是遍历链表并记录前驱节点,修改指针,时间为O(n).删除节点的实质为更改后驱指针指向.这里,复制C的内容至B(此时 ...

  2. Java实现蓝桥杯 算法提高 八皇后 改

    **算法提高 8皇后·改** 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 规则同8皇后问题,但是棋盘上每格都有一个数字,要求八皇后所在格子数字之和最大. 输入格式 一个8*8的棋 ...

  3. 【算法】八皇后问题 Python实现

    [八皇后问题] 问题: 国际象棋棋盘是8 * 8的方格,每个方格里放一个棋子.皇后这种棋子可以攻击同一行或者同一列或者斜线(左上左下右上右下四个方向)上的棋子.在一个棋盘上如果要放八个皇后,使得她们互 ...

  4. 从一道算法题实现一个文本diff小工具

    众所周知,很多社区都是有内容审核机制的,除了第一次发布,后续的修改也需要审核,最粗暴的方式当然是从头再看一遍,但是编辑肯定想弄死你,显然这样效率比较低,比如就改了一个错别字,再看几遍可能也看不出来,所 ...

  5. 【每天一道算法题】时间复杂度为O(n)的排序

    有1,2,……一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度为O(1),使用交换,而且一次只能交换两个数. 这个是以前看到的算法题,题目不难.但是要求比较多,排序算法中,时间 ...

  6. 算法学习 八皇后问题的递归实现 java版 回溯思想

    1.问题描述 八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行.纵行或 ...

  7. 提前批笔试一道算法题的Java实现

    题目描述 这是2021广联达校招提前批笔试算法题之一. 我们希望一个序列中的元素是各不相同的,但是理想和显示往往是有差距的.现在给出一个序列A,其中难免有相同的元素,现在提供了一种变化方式,使得经过若 ...

  8. 每天一道算法题-leetcode136-只出现一次的数字

    前言 打卡第一天 2019.10.26日打卡 算法,即解决问题的方法.同一个问题,使用不同的算法,虽然得到的结果相同,但是耗费的时间和资源是不同的.这就需要我们学习算法,找出哪个算法更好. 大家都知道 ...

  9. 一道算法题加深我对C++中map函数的理解

    一.一道题目引发我对map函数的考量 首先是题目大意:有n个银行,a[i]表示这个人在第i个银行有a[i]块钱(可以是负数),所有银行的钱加起来正好是0.每次只能在相邻的银行之间转账,问最少要转多少次 ...

随机推荐

  1. 如何去除内联元素(inline-block元素)之间的间距

    <body><a href="http://www.baidu.com">百度</a><a href="http://www.i ...

  2. 【lua】如何倒序查找字符

    现在有这样一个需求,有一个字符串,需要查找字符i最后出现的位置,不过相对于其他语言来说,Lua并没有提供这一操作,那么如何是好? 现在有这样几个方法: string.sub(str, i ,j) 功能 ...

  3. HDU 5698——瞬间移动——————【逆元求组合数】

    瞬间移动 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submis ...

  4. Firebird Procedure 带返回的存储过程

    火鸟定义带返回的存储过程是这样,先定义返回结果字段列表,然后为返回字段一一赋值,当你需要返回一行时,就suspend. 当需要返回多行时,就再次为返回字段变量赋值,suspend. 示例: creat ...

  5. ajax返回整个页面

       

  6. SEO学习

    一.什么是SEO SEO是由英文Search Engine Optimization缩写而来, 中文意译为“搜索引擎优化”!SEO是指通过对网站进行站内优化(网站结构调整.网站内容建设.网站代码优化等 ...

  7. ecs CentOS 7 安装 mariadb

    检查之前是否已经安装 rpm -qa | grep mariadb 如果已安装,卸载 yum remove mysql mysql-server mysql-libs compat-mysql51 开 ...

  8. 9、springboot之处理静态资源

    在springboot项目中的resource根目录下建立三个文件夹static.public.resources 里面都放同样名字的图片 但是图片内容不一样 启动springboot之后输入 htt ...

  9. PHP+Xdebug实现远程调试

    以前以为php调试时服务器端和IDE必须在同一台机子上,无意发现xdebug其实是支持远程调试的. 尝试之后发现可以配置成功,还是可以调试代码的感觉爽啊!   php所在Ubuntu服务器       ...

  10. 纯css画三角形,勾等形状

    //三角形 .money-ul li.active:after { content: ""; position: absolute; bottom: 0; right: 0; bo ...