问题描述

会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。 对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2...b8,其中bi为相应摆法中第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。 
输入数据
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1 <= b <= 92)
输出要求
n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串
输入样例
2
1
92

输出样例
15863724
84136275

解题思路一

因为要求出92种不同摆放方法中的任意一种,所以我们不妨把92种不同的摆放方法一次性求出来,存放在一个数组里。为求解这道题我们需要有一个矩阵仿真棋盘,每次试放一个棋子时只能放在尚未被控制的格子上,一旦放置了一个新棋子,就在它所能控制的所有位置上设置标记,如此下去把八个棋子放好。当完成一种摆放时,就要尝试下一种。若要按照字典序将可行的摆放方法记录下来,就要按照一定的顺序进行尝试。也就是将第一个棋子按照从小到大的顺序尝试;对于第一个棋子的每一个位置,将第二个棋子从可行的位置从小到大的顺序尝试;在第一第二个棋子固定的情况下,将第三个棋子从可行的位置从小到大的顺序尝试;依次类推。
首先,我们有一个8*8的矩阵仿真棋盘标识当前已经摆放好的棋子所控制的区域。用一个有92行每行8个元素的二维数组记录可行的摆放方法。用一个递归程序来实现尝试摆放的过程。基本思想是假设我们将第一个棋子摆好,并设置了它所控制的区域,则这个问题变成了一个7皇后问题,用与8皇后同样的方法可以获得问题的解。那我们就把重心放在如何摆放一个皇后棋子上,摆放的基本步骤是:从第1到第8个位置,顺序地尝试将棋子放置在每一个未被控制的位置上,设置该棋子所控制的格子,将问题变为更小规模的问题向下递归,需要注意的是每次尝试一个新的未被控制的位置前,要将上一次尝试的位置所控制的格子复原。

参考程序一

#include <stdio.h>
#include <math.h>
int queenPlaces[92][8]; //存放92种皇后棋子的摆放方法
int count = 0;
int board[8][8]; //仿真棋盘
void putQueen(int ithQueen); //递归函数,每次摆好一个棋子void main()
{int n, i, j;  for(i = 0; i < 8; i++){  // 初始化for(j = 0; j < 8; j++)board[i][j] = -1;for(j = 0; j < 92; j++)queenPlaces[j][i] = 0;}putQueen(0); //从第0个棋子开始摆放,运行的结果是将queenPlaces生成好scanf("%d", &n);for(i = 0; i < n; i++){int ith;scanf("%d", &ith);for(j = 0; j < 8; j++)printf("%d", queenPlaces[ith - 1][j]);printf("\n");}
}
void putQueen(int ithQueen){int i, k, r;if(ithQueen == 8){count ++;return;}for(i = 0; i < 8; i++){if(board[i][ithQueen] == -1){//摆放皇后board[i][ithQueen] = ithQueen;//将其后所有的摆放方法的第ith个皇后都放在i+1的位置上//在i增加以后,后面的第ith个皇后摆放方法后覆盖此时的设置for(k = count; k < 92; k++)queenPlaces[k][ithQueen] = i + 1;//设置控制范围for(k = 0; k < 8; k++)for(r = 0; r < 8; r++)if(board[k][r] == -1 && (k == i || r == ithQueen || abs(k - i) == abs(r - ithQueen))) board[k][r] = ithQueen;//向下级递归putQueen(ithQueen + 1);//回溯,撤销控制范围for(k = 0; k < 8; k++)for(r = 0; r < 8; r++)if(board[k][r] == ithQueen) board[k][r] = -1;}}
}

解题思路二

上面的方法用一个二维数组来记录棋盘被已经放置的棋子的控制情况,每次有新的棋子放置时用了枚举法来判断它控制的范围。还可以用三个一维数组来分别记录每一列,每个45度的斜线和每个135度的斜线上是否已经被已放置的棋子控制,这样每次有新的棋子放置时,不必再搜索它的控制范围,可以直接通过三个一维数组判断它是否与已经放置的棋子冲突,在不冲突的情况下,也可以通过分别设置三个一维数组的相应的值,来记录新棋子的控制范围。

参考程序二

#include <stdio.h>
int  record[92][9], mark[9], count = 0; //record记录全部解,mark记录当前解;
bool range[9], line1[17], line2[17]; //分别记录列方向,45度,135度方向上被控制的情况
void tryToPut(int ); //求全部解的过程
void main()
{int i, testtimes, num;scanf("%d", &testtimes);for(i = 0; i <=8; i++)range[i] = true;for(i = 0; i < 17; i ++)line1[i] = line2[i] = true;tryToPut(1);while(testtimes --){scanf("%d", &num);for(i = 1; i <=8; i++)printf("%d", record[num - 1][i]);printf("\n");}
}void tryToPut(int i){if(i > 8){ //如果最后一个皇后被放置完毕,将当前解复制到全部解中for(int k = 1; k < 9; k ++) record[count][k] = mark[k];count ++;}                    for(int j=1; j<=8; j++){ 逐一尝试将当前皇后放置在不同列上if(range[j] && line1 [i + j] && line2[i - j + 9]){ //如果与前面的不冲突,//则把当前皇后放置在当前位置mark[i] = j;range[j] = line1[i + j] = line2[i - j + 9] = false;tryToPut(i + 1);range[j] = line1[i + j] = line2[i - j + 9] = true;}}
}

解题思路三

这个题目也可以不用仿真棋盘来模拟已放置棋子的控制区域,而只用一个有8个元素的数组记录已经摆放的棋子摆在什么位置,当要放置一个新的棋子时,只需要判断它与已经放置的棋子之间是否冲突就行了。

参考程序三

#include <stdio.h>
int ans[92][8], n, b, i, j, num, hang[8];
void queen(int i){int j, k;if(i == 8){ //一组新的解产生了for(j = 0; j < 8; j++)  ans[num][j] = hang[j] + 1;num++;return;}for (j=0; j<8; j++){ //将当前皇后i逐一尝试放置在不同的列for(k=0; k<i; k++) //逐一判定i与前面的皇后是否冲突if( hang[k] == j || (k - i) == (hang[k] - j) || (i - k) == (hang[k] - j )) break;if (k == i) {  //放置i,尝试第i+1个皇后hang[i] = j;queen(i + 1);}}
}
void main( ){num=0;queen(0);scanf(“%d”, &n);for(i = 0; i < n; i++){scanf(“%d”, &b);for(j = 0; j < 8; j++)  printf(“%d”, ans[b - 1][j]);printf(“\n”);}
}

实现中常见的问题

问题一: 使用枚举法,穷举8个皇后的所有可能位置组合,逐一判断是否可以互相被吃掉,得到超时错误;
问题二:对于多组输入,有多组输出,没有在每组输出后加换行符,得到格式错;
问题三:对输入输出的函数不熟悉,试图将数字转换成字符或者将8个整数转换成8位的十进制整数来完成输出,形成不必要的冗余代码。

算法总结——八皇后问题(三种解法)相关推荐

  1. n皇后问题的三种解法

    N皇后问题是一个经典的问题,在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行.同一列.同一斜线上的皇后都会自动攻击). n皇后问题不算是陈词滥调,也是老生常谈了,作为回溯的经典案例 ...

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

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

  3. 爬山法求解八皇后问题的全部解法

    爬山法求解八皇后问题的全部解法 程序的概要设计思想 初始状态 冲突函数 寻找邻居状态 寻找全部解集 程序主要函数的作用 运行结果截图 Python源代码 程序的概要设计思想 爬山算法是一种局部贪婪算法 ...

  4. 回溯算法解决八皇后_4皇后问题和使用回溯算法的解决方案

    回溯算法解决八皇后 4-皇后问题 (4 - Queen's problem) In 4- queens problem, we have 4 queens to be placed on a 4*4 ...

  5. 背包问题knapsack的三种解法(Python 和 C)

    最近研究了一下0-1背包问题,题目就不复述了,大家应该都知道的. 确切的说不是三种解法而是四种解法,下面我就一一写来. 0.枚举法 这种是最简单的一种做法,当然也是时间空间复杂度最大的方法,得到的肯定 ...

  6. 寻找两个有序数组的中位数(附上三种解法)

    目录 •写在前面 •题目 •解法一 •解法二 •解法三 •结束 •写在前面 这道题比较经典,我当时在做的时候,想出了两种解决方案,不过总感觉算法不够优美,所以找到了另一种我觉得非常精妙的解法,利用了K ...

  7. Python实现阶乘的三种解法

    Python实现阶乘的三种解法 问题描述 输入一个正整数n,输出n!的值. 其中n!=123*-*n. 算法描述 n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法.使用一个数组A来 ...

  8. [简单题]自定义取余(三种解法)C++实现

    题目链接: 点击打开原题链接 题目意思,就是标题意思. 第一种解法:(加法迭代)用加法来模拟这个(17行代码) int mod256WithoutMod(int number) {if (number ...

  9. jsp判断字符串相等_最长回文字符串三种解法

    先解释一下什么是回文字符串,比如说字符串"aba",无论是从先往后读取还是从后往前读取,结果都是一样的.当给定很长的字符串时,如何快速获取到最长的回文字符串,这也是大厂比较常见的算 ...

  10. 【三种解法】剑指 Offer 06. 从尾到头打印链表【附完整可运行代码】

    立志用最少的代码做最高效的表达 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回). 示例 1: 输入:head = [1,3,2] 输出:[2,3,1] 限制: 0 <= 链表 ...

最新文章

  1. sublime text3的php代码合法检查
  2. 使用cloudera manager搭建HUE后的使用,包括Oozie
  3. li span 时间向右排版问题
  4. Ubuntu18.04应用程序安装集锦
  5. 前端开发 html常用标签 0229
  6. python结束程序再重新执行_Python对象对重新执行程序的持久性
  7. awk java_Linux三剑客之awk
  8. c#实现16进制和字符串之间转换的代码
  9. Tricks(四十七)—— 布尔矩阵(0-1矩阵)取反
  10. splice slice
  11. 你们知道为什么数据库的交互技术要叫JDBC吗?
  12. C语言基础入门实例汇总(共65个案例)
  13. Office2016+Visio2016安装过程
  14. win10 任务栏 网络 图标 消失 空白 network location awareness 错误1068
  15. 时间片轮转调度算法(Java)
  16. ipad为什么显示itunes store无法连接服务器,ipad无法连接itunes store怎么办
  17. 判断IP是否在IP段内
  18. 伪装学渣未删减部分_慎重勇者:破坏神和圣哉做了什么?第9话战帝被删减剧情补充...
  19. 宇宙也能测量,破解未解之谜的三维地图出炉
  20. 这里告诉大家,“后端开发工程师”到底是做什么的。

热门文章

  1. linux网卡的vlan配置,linux增加vlan网卡配置
  2. 自定义QQ名片[FoxNest]
  3. 2021 CISP核心知识点 - 刷题笔记
  4. 基于Linux服务器的JAVA开发环境搭建
  5. 用计算机编制的设计文件包括,城市规划图集计算机编制.doc
  6. npm install常见报错及问题
  7. 关于java的输入输出
  8. 借贷宝人脸识别无需绑卡,需合作者共同冲刺
  9. 计算机专业轻薄本可以吗,轻薄笔记本电脑推荐,锐智系创造本不可“轻”视!...
  10. 化妆品眼影调色板HRIPT RIPT皮肤斑贴测试流程