课设——八皇后问题(N皇后解决)
1. 问题定义与需求分析
1、问题描述:
八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
基本要求:
在一个8×8的棋盘里放置8个皇后,要求每个皇后两两之间不相"冲突"(在每一横列竖列斜列只有一个皇后)。
1、冲突。包括行、列、两条对角线:
(1)列:规定每一列放一个皇后,不会造成列上的冲突;
(2)行:当第i行被某个皇后占领后,则同一行上的所有空格都不能再放皇后,要把以i为下标的行位置标为被占领状态;
(3)对角线:对角线有两个方向。在同一对角线上的所有点(设下标为(i,j)),要么(i+j)是常数,要么(i-j)是常数。因此,当第i个皇后占领了第j列后,要同时把以(i+j)、(i-j)为下标的标记置为被占领状态。
2、数据结构。
(1)解数组A。A[i]表示第i个皇后放置的列;范围:1..8
(2)行冲突标记数组B。B[i]=0表示第i行空闲;B[i]=1表示第i行被占领;范围:1..8
(3)对角线冲突标记数组C、D。
C[I-J]=0表示第(I-J)条对角线空闲;C[I-J]=1表示第(I-J)条对角线被占领;范围:-7..7
D[I+J]=0表示第(I+J)条对角线空闲;D[I+J]=1表示第(I+J)条对角线被占领;范围:2..16
实现提示:
1、数据初始化。
2、从n列开始摆放第n个皇后(因为这样便可以符合每一竖列一个皇后的要求),先测试当前位置(n,m)是否等于0(未被占领):如果是,摆放第n个皇后,并宣布占领,接着进行递归;如果不是,测试下一个位置(n,m+1),但是如果当n<=8,m=8时,却发现此时已经无法摆放时,便要进行回溯。
3、当n>8时,便一一打印出结果。
4.回溯算法的实现
(1)为解决这个问题,我们把棋盘的横坐标定为i,纵坐标定为j,i和j的取值范围是从1到8。当某个皇后占了位置(i,j)时,在这个位置的垂直方向、水平方向和斜线方向都不能再放其它皇后了。用语句实现,可定义如下三个整型数组:a[8],b[15],c[24]。
其中:
a[j-1]=1 第j列上无皇后
a[j-1]=0 第j列上有皇后
b[i+j-2]=1 (i,j)的对角线(左上至右下)无皇后
b[i+j-2]=0 (i,j)的对角线(左上至右下)有皇后
c[i-j+7]=1 (i,j)的对角线(右上至左下)无皇后
c[i-j+7]=0 (i,j)的对角线(右上至左下)有皇后
(2)为第i个皇后选择位置的算法如下:
for(j=1;j<=8;j++) /*第i个皇后在第j行*/
if ((i,j)位置为空)) /*即相应的三个数组的对应元素值为1*/
{占用位置(i,j) /*置相应的三个数组对应的元素值为0*/
if i<8为i+1个皇后选择合适的位置;
else 输出一个解
}
2.概要设计
一行一行的放置皇后,所以不需要判断行冲突。判断列冲突很简单,直接和前面的比一下是否一样即可,而对于对角线冲突,就有一个特殊的小技巧:由于每一条主对角线(x-y)是一定的,每一条副对角线(x+y)是一定的。于是,我们通过判断那些定值与前面已经放置的皇后的定值比较即可判断是否冲突。
在最终的N皇后求解程序中,除了算法部分,还加入了界面优化,多次求解的询问,以及清屏操作。
3.详细设计
数据结构设计
A表示第i个皇后放置的列 (解数组)
B表示列冲突标记数组
C、D表示对角线冲突标记数组:处理的时候注意为了不让数组越界C[i+j-2] D[i-j+7]
N 皇后 C[i+j-2] D[i-j+n-1]
算法求解部分伪代码如下:
为第i个皇后选择所在行
{
从第一个位置开始一个一个尝试
{
if 该位置合法
{
放置并标记冲突位置
if 所有皇后还未处理完
放置 第i+1个皇后
else
找到一个解并输出
回溯 把之前的标记还原 (下一个位置可能放置成功了也可能失败了)
}
}
}
4. 编码与测试分析
测试:
源代码如下:
#include<iostream>#include<stdio.h>#include<stdlib.h>using namespace std;const int MAXN = 100; //n皇后最大n=100int ans;int A[MAXN], B[MAXN], C[2 * MAXN], D[2 * MAXN];/*A表示第i个皇后放置的列 (解数组)B表示列冲突标记数组C、D表示对角线冲突标记数组:处理的时候注意为了不让数组越界C[i+j-2] D[i-j+7]N 皇后 C[i+j-2] D[i-j+n-1]*/void show(int* a, int n){cout << "case" << ans << ":" << endl;for (int i = 1; i <= n; i++){int c = a[i];for (int i = 1; i < c; i++) cout << "[]";cout << " &";for (int j = 1; j <= n - c; j++) cout << "[]";cout << endl;}cout << endl;}void solve(int i, int n)//为第i个皇后选择所在行{for (int j = 1; j <= n; j++){if ((B[j] == 0) && (C[i + j - 2] == 0) && (D[i - j + n - 1] == 0)) //该位置合法{//cout << "i: " << i << "j: " << j << endl;A[i] = j;//放置并标记冲突位置B[j] = 1;C[j + i - 2] = 1;D[i - j + n - 1] = 1;if (i < n){solve(i + 1, n); //放置下一个皇后}else {ans++;show(A, n);}//回溯 把之前的标记还原 (下一个位置可能放置成功了也可能失败了)B[j] = 0;C[j + i - 2] = 0;D[i - j + n - 1] = 0;}}}int main(){system("color F5");int n, ch=1;while (ch){cout << "N皇后问题求解(输入N):";cin >> n;ans = 0;memset(A, 0, sizeof(int));memset(B, 0, sizeof(int));memset(C, 0, sizeof(int));memset(D, 0, sizeof(int));//初始化solve(1, n);if (!ans) cout << "该问题无解" << endl;cout << endl << endl << endl << "是否继续求解?(1是0否)";cin >> ch;system("cls"); //清屏 }return 0;}
5.结束语
求解过程遇到的问题:
- 对于回溯位置的选取:一开始其实是不太理解应该在哪个地方进行回溯的。因为在需求中给出了整体算法的框架,关键的回溯操作空出来了。基于这个问题是要求多解,因此在搜索过程中必然需要用到回溯。值得注意的是这个问题需要回溯的情况有两种
- 已经找到一解。(多解)
- 无法继续求解。(求解)
第一种情况回溯实现的是多解,而第二种情况实现的是求解。理解了这一点回溯的位置自然也就很容易找到了。
- 对于递归的理解:本题对于回溯的操作是在下一步的递归后面还原上一步的标记(也就是回溯),一开始对于这里也有疑惑。为什么只还原上一步的标记,递归过程中每走一步状态标记数组都会发生变化。这里需要明确和真正理解什么是递归,它实际上是一层一层嵌套的结果,也就是说内层的状态改变只会影响更内层的,而不会影响外层递归。
6.参考文献(网址)
https://blog.csdn.net/qinghezhen/article/details/17849837
主要是参考这篇博客里面给出的N皇后答案个数,依次来验证自己写的程序是否正确。
课设——八皇后问题(N皇后解决)相关推荐
- 操作系统课设--使用信号量解决生产者/消费者同步问题
山东大学操作系统课设lab3 实验三 使用信号量解决生产者/消费者同步问题(lab3) 实验目的 理解Nachos的信号量是如何实现的 生产者/消费者问题是如何用信号量实现的 在Nachos中是如何创 ...
- 【恋上数据结构】回溯、剪枝(八皇后、n皇后)、LeetCode51.N皇后、LeetCode52.N皇后 II
回溯 回溯(Back Tracking) 提出八皇后问题(Eight Queens) 初步思路一:暴力出奇迹 初步思路二:根据题意减少暴力程度 初步思路三:回溯法(回溯+剪枝) 四皇后 - 回溯法图示 ...
- 大学期间所有课设及大作业源代码
程序员练成记 出处:牟尼的专栏 http://blog.csdn.net/u012027907 记得刚上大一时,那时对这个专业(软件工程)很陌生,甚至对电脑都很陌生,有时还有点儿害怕,因为我在进入大学 ...
- 计算机组成原理文华学院,华中科技大学文华学院计算机组成原理课设.doc
<华中科技大学文华学院计算机组成原理课设.doc>由会员分享,提供在线免费全文阅读可下载,此文档格式为doc,更多相关<华中科技大学文华学院计算机组成原理课设.doc>文档请在 ...
- 2021年数据库课设该怎么做?一个超市管理系统,简单的前后端分离项目,带你从概要设计走到项目发布!(Vue.js+SpringBoot+MybatisPlus)
由于本文格式原来是word,所以文中有些格式不太对.如果这篇文章对你有帮助,麻烦点赞评论一下谢谢!源码和word文档可私聊领取~ 目录 一.相关技术介绍 1.1 RDBMS: 1.2应用程序开发环境: ...
- QT五子棋游戏课设及源码(连接mysql数据库含打开并运行程序的教程)
gdut大一下学期c++课设(得分:95) 实验报告及源码压缩包百度云下载: 链接:https://pan.baidu.com/s/1zO5ofMz09fiWihxCcZcFbg 提取码:ddav 首 ...
- 皇后问题,8皇后、n皇后、2n皇后
8皇后问题 问题描述: 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例. 该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出: 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意 ...
- java魔塔_2018-2019学年第一学期Java课设--魔塔
Magic-Towers 一.团队名称.团队成员介绍.任务分配 团队名称:MoTa 团队成员介绍 网络1713柳聪灵[组长] 201721123065 网络1712李梦冰 201721123040 网 ...
- 单片机课设基于51单片机的波形发生器(公开资源)(四种波形)(同时输出两种波形)
单片机课设-波形发生器 前言 一.课设任务是什么? 二.如何解决这几个任务? 三.仿真原理图 四.代码 4.1 LCD1602代码 4.2 波形输出以及8*8点阵显示代码 4.3 波形选择 五.仿真源 ...
- 手写体汉字识别(分割+卷积识别)[2021课设论文]
本文为课设论文:对于汉字数字的识别,模型搭建和代码并不是难点,预处理才显得重要和困难.虽然模型准确率能达到90%~95%,但是也存在没解决的问题. 如有需要,可以私信提供完整代码工程及其数据 ...
最新文章
- 如何面试java后端_近期面试Java后端的一些感悟
- 迁移svn项目到git
- java docx转html实例_Java实现将word转换为html的方法示例【doc与docx格式】
- Angular自学笔记(?)属性型指令
- [Leetcode][第207题][JAVA][课程表][拓扑排序][DFS]
- oracle表分析都分析什么,oracle表分析
- 移动端:判断是否微信端、判断手机操作系统(ios或android)
- 返回一个整数数组中最大子数组的和---环形数组
- Grunt的配置及使用(压缩合并js/css)
- python批量读取图片并复制入word_提取word文档中的图片并使用Python进行批量格式转换,出,Word,里,利用,python...
- ThreadInfo结构和内核栈的两种关系
- J2EE框架技术(SpringMVC) 知识点笔记(1)
- 大数据培训分享大数据六大核心技术
- 田园综合体建设指导手册
- VR/AR/MR/XR 几种虚拟现实技术的区别
- dcos marathon - 容器的存储
- [初学Spring Boot](1):打不开localhost:8080/hello
- python向json文件写入中文信息
- 标贝科技声音克隆技术赋能 定制语音功能让陪伴触手可及
- linux学习lesson25