八皇后问题

一、题意解析

  国际象棋中的皇后,可以横向、纵向、斜向移动。如何在一个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. table定位

    Table定位 在 web 页面中经常会遇到 table 表格,特别是后台操作页面比较常见.本篇详细讲解 table 表格如何定位. 1.1 table特性 1.table 页面查看源码一般有这几个明 ...

  2. ios UISearchDisplayController 实现 UITableView 搜索功能

    UISearchDisplayController 是苹果专为 UITableView 搜索封装的一个类. 里面内置了一个 UITableView 用于显示搜索的结果.它可以和一个需要搜索功能的 co ...

  3. Stirng,Stringbuffer,Stringbuild的区别浅淡

    String 1,Stirng是对象不是基本数据类型 2,String是final类,不能被继承.是不可变对象,一旦创建,就不能修改它的值. 3,对于已经存在的Stirng对象,修改它的值,就是重新创 ...

  4. PHP自然排序,非自然排序(未完成)

    还要研究一下,暂时先添加个链接 参考:PHP数组的“自然”排序

  5. WEB项目构建优化之自动清除CSS中的图片缓存

    在web项目构建发布时,经常遇到css中图片的修改优化,那么如何清除图片的缓存成为必须要解决的问题.曾经有过傻傻的方法就是直接在图片后面添加随机数.今天主要是从构建自动化方式来解决这个问题,提高开发及 ...

  6. 常用工具说明--Maven使用说明

    什么是Maven? 如今我们构建一个项目需要用到很多第三方的类库,如写一个使用Spring的Web项目就需要引入大量的jar包.一个项目Jar包的数量之多往往让我们瞠目结舌,并且Jar包之间的关系错综 ...

  7. C++命名空间使用代码

    namesp.h #pragma once #include <string> namespace pers { using namespace std; struct Person { ...

  8. [shell]管理 Sphinx 启动|停止|重新生成索引的脚本

    对于启动sphinx的服务,可以直接输入如下命令 /usr/bin/searchd -c /etc/sphinx/sphinx.conf <!-- /usr/local/bin/searchd  ...

  9. Oracle 数据库字典 sys.obj$ 表中关于type#的解释

    sys.obj$ 表是oracle 数据库字典表中的对象基础表,所有对象都在该表中有记录,其中type#字段表明对象类型,比如有一个表 test ,则该对象在sys.obj$ 中存在一条记录,name ...

  10. python2文件转换为exe可执行文件

    windows下py文件的运行需要安装python,如果是exe文件就可以直接运行 1. 直接在命令行用pip安装 pyinstaller pip install pyinstaller 2 在命令行 ...