八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后,为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当n = 1或n ≥ 4时问题有解。

八皇后问题最早是由西洋棋棋手马克斯·贝瑟尔(Max Bezzel)于1848年提出。第一个解在1850年由弗朗兹·诺克(Franz Nauck)给出。并且将其推广为更一般的n皇后摆放问题。诺克也是首先将问题推广到更一般的n皇后摆放问题的人之一。

在此之后,陆续有数学家对其进行研究,其中包括高斯和康托,1874年,S.冈德尔提出了一个通过行列式来求解的方法,这个方法后来又被J.W.L.格莱舍加以改进。

1972年,艾兹格·迪杰斯特拉用这个问题为例来说明他所谓结构化编程的能力。他对深度优先搜索回溯算法有着非常详尽的描述。

八个皇后在8x8棋盘上共有4,426,165,368 种摆放方法,但只有92个互不相同的解。如果将旋转和对称的解归为一种的话,实际上一共只有12个独立解,

以上信息摘自维基百科 https://zh.wikipedia.org/zh-hans/%E5%85%AB%E7%9A%87%E5%90%8E%E9%97%AE%E9%A2%98

闲来无事,写了一段八皇后解题方法,共输出 92 种解题方案。

两种算法输出:分别是 eight.cpp 调用的 GenerateLoop() 循环嵌套算法,以及后的递归算法 GenerateRecursion(),两种算法本质相同,都是逐层搜索、回退、再搜索。而递归算法因为不受循环嵌套的限制,通过修改 main.h 中的“纵向数量”和“横向数量”的数值,可以实现 n×n 的计算,例如 10×10 的计算将找到 724 种解,以此类推。

eight.cpp,入口程序,创建八皇后对象 (封装在 main.h 和 main.cpp),EightQueen 对象有两个主要的生成函数,循环嵌套搜索算法 GenerateLoop() 和递归算法 GenerateRecursion(),它们分别执行生成过程和打印结果。

// eight.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include "main.h"using namespace std;int main()
{// 创建八皇后对象EightQueen* eightQueen = new EightQueen();// 生成题解, 逐层搜索搜索, 层级受限eightQueen->InitCheckerboard();eightQueen->GenerateLoop();getchar();// 生成题解, 递归搜索算法eightQueen->InitCheckerboard();eightQueen->GenerateRecursion();getchar();// 释放对象delete eightQueen;return 0;
}

main.h,对象定义,封装所需的函数和内部变量。

#pragma once#ifndef EIGHT_MAIN
#define EIGHT_MAIN// 纵向数量, 递归状态下可以随意扩大
#define CHECKER_BOARD_ROW 8
// 横向数量, 递归状态下可以随意扩大
#define CHECKER_BOARD_COLUMN 8class EightQueen
{
private:// 定义棋盘结构int checkerboard[CHECKER_BOARD_ROW][CHECKER_BOARD_COLUMN];// 初始化当前行void ClearRow(int row);// 检查向上冲突bool CheckVerticalByUp(int row, int column);// 检查左上角冲突bool CheckUpperLeftCorner(int row, int column);// 检查右上角冲突bool CheckUpperRightCorner(int row, int column);// 打印八皇后棋盘void TablePrint();// 计数int intPrintCount = 0;public:// 初始化棋盘void InitCheckerboard();// 生成八皇后题解, 方法 1 嵌套循环void GenerateLoop();// 生成八皇后题解, 方法 2 递归void GenerateRecursion(int row = 0);EightQueen();~EightQueen();
};#endif    

main.cpp,主要代码的对象封装。

/** 2018-8-13** 创建一个 8x8 棋盘, 0 表示没有皇后,1表示存在皇后** 循环嵌套算法实现* EightQueen::GenerateLoop()** 递归算法实现* EightQueen::GenerateRecursion(int row)** loop begin* 逐层循环,第一层不做检查* 每一层的每一列进行检查* 取坐标,检查向上是否存在冲突,如果有则返回 false,否则返回 true* 取坐标,检查左上角方向是否存在冲突,如果有则返回 false,否则返回 true* 取坐标,检查右上角方向是否存在冲突,如果有则返回 false,否则返回 true* 将皇后设置到某个指定的坐标* loop end**/#include "stdafx.h"
#include <stdio.h>
#include "main.h"// using namespace std;EightQueen::EightQueen()
{
}EightQueen::~EightQueen()
{
}// 初始化棋盘
void EightQueen::InitCheckerboard()
{for (int i = 0; i < CHECKER_BOARD_ROW; i++){for (int j = 0; j < CHECKER_BOARD_COLUMN; j++){checkerboard[i][j] = 0;}}// 计数器intPrintCount = 0;
}// 打印八皇后解题表格
void EightQueen::TablePrint()
{// 逐行输出棋盘信息for (int row = 0; row < CHECKER_BOARD_ROW; row++){// 设置表宽度const int PrintLineLen = CHECKER_BOARD_COLUMN * 2;// 定义输出表的行, +1 需要一个字符串结束符 0x0char strPrintLine[PrintLineLen + 1];// 初始化输出表的行memset(strPrintLine, 0x0, PrintLineLen + 1);// 绘制棋盘行, 用 " " 和 "." 标记for (int i = 0; i < PrintLineLen; i++){// 创建表格, 留一空格跳空,更易于识别if (i % 2 == 0){strPrintLine[i] = '.';}else{strPrintLine[i] = ' ';}}// 遍历棋盘的行, 找到皇后, 则标记为 'x'for (int i = 0; i < CHECKER_BOARD_COLUMN; i++){// 找到一个皇后,标记为 xif (checkerboard[row][i] == 1){// 跳空置子strPrintLine[i * 2] = 'x';}}// 打印一行printf("%s\n", strPrintLine);}
}// 检查垂直向上的冲突
bool EightQueen::CheckVerticalByUp(int row, int column)
{// 避开当前的皇后位置row--;// 保持列,检查所有行是否存在皇后while (row >= 0){int val = checkerboard[row--][column];if (val == 1){return false;}}return true;
}// 检查左上对角线的冲突
bool EightQueen::CheckUpperLeftCorner(int row, int column)
{// 避开当前的皇后row--;column--;// 检查左上角所有的位置是否有皇后while (row >= 0 && column >= 0){int val = checkerboard[row--][column--];if (val == 1){return false;}}return true;
}// 检查右上对角线的冲突
bool EightQueen::CheckUpperRightCorner(int row, int column)
{// 避开当前的皇后row--;column++;// 检查左上角所有的位置是否有皇后while (row >= 0 && column < CHECKER_BOARD_COLUMN){int val = checkerboard[row--][column++];if (val == 1){return false;}}return true;
}// 初始化当前行
void EightQueen::ClearRow(int row)
{for (int i = 0; i < CHECKER_BOARD_COLUMN; i++){checkerboard[row][i] = 0;}
}// 逐个生成八皇后位置 递归算法
void EightQueen::GenerateRecursion(int row)
{// 找到结果 显示结果并返回if (row == CHECKER_BOARD_ROW){// row == CHECKER_BOARD_ROW 已经完成了棋盘上全部 row 的布子// 打印棋盘TablePrint();printf("No.%d\n", ++intPrintCount);return;}// 在当前 row 内找到一个适合的位置放置皇后for (int c = 0; c < CHECKER_BOARD_COLUMN; c++){// 第一行不作检查if (row == 0){}else{// 向上检查垂直冲突if (CheckVerticalByUp(row, c) == false){continue;}// 检查左上角冲突if (CheckUpperLeftCorner(row, c) == false){continue;}// 检查右上角冲突if (CheckUpperRightCorner(row, c) == false){continue;}}// 当前 row 找到一个适合的位置// 清空当前行ClearRow(row);// 置子checkerboard[row][c] = 1;// 递归进入下一行GenerateRecursion(row + 1);// 若循环内全部被 continue,将回退到上一 row 重新分配位置,直到全部棋盘可能性搜索完}
}// 逐行生成八皇后位置,循环嵌套算法
void EightQueen::GenerateLoop()
{// 计数器int count = 0;// 第1行for (int c0 = 0; c0 < CHECKER_BOARD_ROW; c0++){int row = 0;ClearRow(row);checkerboard[row][c0] = 1;// 第2行for (int c1 = 0; c1 < CHECKER_BOARD_ROW; c1++){int row = 1;// 向上检查垂直冲突if (CheckVerticalByUp(row, c1) == false){continue;}// 检查左上角冲突if (CheckUpperLeftCorner(row, c1) == false){continue;}// 检查右上角冲突if (CheckUpperRightCorner(row, c1) == false){continue;}// 放置皇后ClearRow(row);checkerboard[row][c1] = 1;for (int c2 = 0; c2 < CHECKER_BOARD_ROW; c2++){int row = 2;// 向上检查垂直冲突if (CheckVerticalByUp(row, c2) == false){continue;}// 检查左上角冲突if (CheckUpperLeftCorner(row, c2) == false){continue;}// 检查右上角冲突if (CheckUpperRightCorner(row, c2) == false){continue;}ClearRow(row);checkerboard[row][c2] = 1;for (int c3 = 0; c3 < CHECKER_BOARD_ROW; c3++){int row = 3;// 向上检查垂直冲突if (CheckVerticalByUp(row, c3) == false){continue;}// 检查左上角冲突if (CheckUpperLeftCorner(row, c3) == false){continue;}// 检查右上角冲突if (CheckUpperRightCorner(row, c3) == false){continue;}ClearRow(row);checkerboard[row][c3] = 1;for (int c4 = 0; c4 < CHECKER_BOARD_ROW; c4++){int row = 4;// 向上检查垂直冲突if (CheckVerticalByUp(row, c4) == false){continue;}// 检查左上角冲突if (CheckUpperLeftCorner(row, c4) == false){continue;}// 检查右上角冲突if (CheckUpperRightCorner(row, c4) == false){continue;}ClearRow(row);checkerboard[row][c4] = 1;for (int c5 = 0; c5 < CHECKER_BOARD_ROW; c5++){int row = 5;// 向上检查垂直冲突if (CheckVerticalByUp(row, c5) == false){continue;}// 检查左上角冲突if (CheckUpperLeftCorner(row, c5) == false){continue;}// 检查右上角冲突if (CheckUpperRightCorner(row, c5) == false){continue;}ClearRow(row);checkerboard[row][c5] = 1;for (int c6 = 0; c6 < CHECKER_BOARD_ROW; c6++){int row = 6;// 向上检查垂直冲突if (CheckVerticalByUp(row, c6) == false){continue;}// 检查左上角冲突if (CheckUpperLeftCorner(row, c6) == false){continue;}// 检查右上角冲突if (CheckUpperRightCorner(row, c6) == false){continue;}ClearRow(row);checkerboard[row][c6] = 1;for (int c7 = 0; c7 < CHECKER_BOARD_ROW; c7++){int row = 7;// 向上检查垂直冲突if (CheckVerticalByUp(row, c7) == false){continue;}// 检查左上角冲突if (CheckUpperLeftCorner(row, c7) == false){continue;}// 检查右上角冲突if (CheckUpperRightCorner(row, c7) == false){continue;}// 找到位置并置子ClearRow(row);checkerboard[row][c7] = 1;// 打印表格printf("No.%d: R0=%d, R1=%d, R2=%d, R3=%d, R4=%d, R5=%d, R6=%d, R7=%d\n", ++count, c0, c1, c2, c3, c4, c5, c6, c7);TablePrint();}}}}}}}}printf("Found %d, press enter to exist.", count);
}

八皇后问题的解输出,两种算法都各找到 92 种解。

Q群讨论 236201801
.

八皇后 C++ 递归算法和循环嵌套算法 共得到 92 种题解相关推荐

  1. C++八皇后拼图,打印所有的算法(附完整源码)

    八皇后拼图,打印所有的算法 八皇后拼图,打印所有的算法的完整源码(定义,实现,main函数测试) 八皇后拼图,打印所有的算法的完整源码(定义,实现,main函数测试) #include <ios ...

  2. 关于python的八皇后问题递归算法详解

    这里是对于周一课上的老师教学的python八皇后问题的个人学习记录 八皇后问题出自国际象棋:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不 ...

  3. 八皇后问题c语言循环,八皇后问题的12组解

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #include #include #define N 8 /*皇后数*/ typedef int bool; rot(char d[ ],char s[ ...

  4. Python(4)循环嵌套算法及冒泡排序

    1.循环嵌套 例:男孩和女孩依次握手 (外层取一个元素,内层循环执行完再执行外层) boys = ['a','b','c','d','e'] girls = ['1','2','3','4','5'] ...

  5. 八皇后非递归算法c语言,要求;编写实现八皇后问题的递归解法或非递归解法,对于任意给定的一? 爱问知识人...

    将下面程序改成运行后需要输入起始位置(第N行第M列)然后输出结果. #include #include enum Status {TRUE,FALSE}; //枚举状态 int matrix[ 将下面 ...

  6. Interview:算法岗位面试—上海某公司算法岗位(偏机器学习,互联网金融行业)技术面试考点之数据结构相关考察点—斐波那契数列、八皇后问题、两种LCS问题

    ML岗位面试:上海某公司算法岗位(偏机器学习,互联网金融行业)技术面试考点之数据结构相关考察点-斐波那契数列.八皇后问题.两种LCS问题 Interview:算法岗位面试-上海某公司算法岗位(偏机器学 ...

  7. 还记得八皇后的解法吗

    "还记得八皇后的解法吗?" "上个世纪的事情,不记得了." "-- 现在回忆一下?" "开会,回头说." " ...

  8. C语言编程统计八皇后问题的解的个数,八皇后问题C语言解法

    偶遇八皇后问题,随即自己写了一个仅供参考 #include #include #define SIZE 8 void Circumsribe(int(*checkerboard)[SIZE], int ...

  9. 八皇后问题(又名: 高斯八皇后)

    题目连接: 八皇后问题 题目: 会下国际象棋的人都很清楚:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题. ...

最新文章

  1. Hibernate关联关系映射
  2. Android官方开发文档Training系列课程中文版:管理设备的睡眠状态
  3. 双目视觉焦距_双目视觉简介
  4. 【NLP】探索NLP模型可解释性的7种姿势
  5. C#LeetCode刷题-记忆化
  6. 打开excel显示php拓展名,新建xls文件提示扩展名不一致
  7. Intellig idea导入项目第一次运行报错- Error running ‘Application‘: Command line is too long—— 解决方法
  8. OpenStack阵营将推VDI平台 挑战思杰、VMware
  9. 物联网云平台有哪些优势
  10. 完整的安全方案需要参考的几个方面
  11. 【笔记】OpenCV3 人脸识别
  12. 博士申请 | 美国弗吉尼亚理工大学周大为老师招收图神经网络方向全奖博士生...
  13. 想学一门技术,学java有前途吗?
  14. 计算机图形学在游戏设计中的应用
  15. iOS多控制器-视图切换.
  16. 计算签到记录的次数统计
  17. 资源暂时不可用错误(Out of memery)完美解决方案
  18. element中滑块组件Slider展示一天24小时的时间问题
  19. nested exception is io.lettuce.core.RedisCommandExecutionException: ERR invalid expire time in setex
  20. PPT如何插入艺术字

热门文章

  1. 视频搬运去重技术深度讲解
  2. gil 简述_GIL学习
  3. Kotlin相关面试题
  4. python3基础教程 邓英_python 3 基础教程
  5. jsfor循环终止_JavaScript跳出循环的三种方法(break, return, continue)
  6. Lucene,Elasticsearch,Solr,Xapian,Sphinx主流搜索引擎的对比
  7. 如何获得NPDP考试课时证明?
  8. cesium--画线
  9. 逆水寒 不显示 服务器,逆水寒服务器状态
  10. Vue2.0 Vue组件 单文件组件