八皇后问题 及 非正式个人代码
2014-09-26 14:57
183 查看
昨天有师兄因为做对了一道八皇后,(当然不止这一道题,一共有三道题),拿到的华为的Special offer,想着这个问题很多年前我也写过。(本人目前研二),晚上闲着无聊就来写写。
八皇后问题描述
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。【摘自百度百科】(其实我觉得就形状而言,应该只有23种结果,其他的都是这23种结果严重中线轴和对角线做的对称)
我的想法
其实我也不确定这是不是我的想法了,这个问题是一个经典的运用递归的问题,既然可以递归,那么我们就要寻找到一个通用的子结构。(逻辑上好像反了呵)
首先,我们放皇后是一层一层来放的,放好了就开始放下一层的皇后,直到八层都放好了,我们就可以得到一个结果。那么针对每层放置皇后的时候,我们可以分成两层来看。
1. 之前的皇后都已经摆好了,即她们无法相互攻击。
2. 遍历这一层的每个位置,并尝试放置皇后,只要无法被之前的皇后攻击到,我们就将放置在这个位置,并进行下一层的皇后放置工作。
大致步骤就是递归的主体思想了。
先贴出代码,然后再进一步说明
先看程序头。
board是定义的一个棋盘,并将所有子初始为0. (0代表无皇后,1代表有皇后)
result是存放结果,一共有92种结果就定义92。
queen函数就是递归函数的主体,layer代表的是层数。
在展示主体函数之前,还有一些用于判定位置是否合法的工具函数。
从名字应该就很好判断各函数的作用了。
这里:
x表示行数
y表示列数
映射到棋盘就是如图所示,我着急的函数英文名想表达的就是在图上向上,向右上,向坐上来查找是否有皇后。
那么红点对应的board的坐标就是board[2][4]。
接来下是主体函数
这里需要明白一件事,当递归函数queen返回时意味着:
第layer层以下的所有摆放皇后位置的方法都已经尝试过一遍了!!!
所以每当我们检测到一个可行的皇后的位置时,所要做的就是将该位置为1,然后尝试该层以下所有摆放皇后的位置的方法。当递归函数执行完之后,我们就将刚找出的那个可行位置置为0,寻找下一个可行位置。
对于第一层,也就是X=0而言,全部的8个位置都是可行的,剩余的就是找出余下7层摆放皇后位置的方法。
当到达第八层,也就是X=7时,每找到一个可行位置,就意味着一个可行解的诞生,这里我们就将结果记录下来。
啊,全部说完了,也
4000
不知道我说明白解法没有。然后就是运行的主函数了,运行queen(0), 然后打印结果。
八皇后问题描述
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。【摘自百度百科】(其实我觉得就形状而言,应该只有23种结果,其他的都是这23种结果严重中线轴和对角线做的对称)
我的想法
其实我也不确定这是不是我的想法了,这个问题是一个经典的运用递归的问题,既然可以递归,那么我们就要寻找到一个通用的子结构。(逻辑上好像反了呵)
首先,我们放皇后是一层一层来放的,放好了就开始放下一层的皇后,直到八层都放好了,我们就可以得到一个结果。那么针对每层放置皇后的时候,我们可以分成两层来看。
1. 之前的皇后都已经摆好了,即她们无法相互攻击。
2. 遍历这一层的每个位置,并尝试放置皇后,只要无法被之前的皇后攻击到,我们就将放置在这个位置,并进行下一层的皇后放置工作。
大致步骤就是递归的主体思想了。
先贴出代码,然后再进一步说明
// EightQueen.cpp // Author:SwineX // Time: 2014.9.25 // Desc Solve EightQueen Problem #include <stdio.h> #define RESULT_NUM 92 int board[8][8] = { 0 }; int result[RESULT_NUM][8][8]; int resultNum = 0; extern int queen(int layer);
先看程序头。
board是定义的一个棋盘,并将所有子初始为0. (0代表无皇后,1代表有皇后)
result是存放结果,一共有92种结果就定义92。
queen函数就是递归函数的主体,layer代表的是层数。
在展示主体函数之前,还有一些用于判定位置是否合法的工具函数。
int goUp(int x, int y) { while (x >= 0) { if (board[x--][y]) { return 0; } } return 1; } int goLeftUp(int x, int y) { while (x >= 0 && y >= 0) { if (board[x--][y--]) { return 0; } } return 1; } int goRightUp(int x, int y) { while (y < 8 && x >= 0) { if (board[x--][y++]) { return 0; } } return 1; }
从名字应该就很好判断各函数的作用了。
这里:
x表示行数
y表示列数
映射到棋盘就是如图所示,我着急的函数英文名想表达的就是在图上向上,向右上,向坐上来查找是否有皇后。
那么红点对应的board的坐标就是board[2][4]。
接来下是主体函数
int queen(int layer) { for (int i = 0; i < 8; i++) { if (goUp(layer - 1, i) && goLeftUp(layer - 1, i - 1) && goRightUp(layer - 1, i + 1)) { if (layer == 7) { board[layer][i] = 1; // 记录结果 for (int j = 0; j < 8; j++) { for (int k = 0; k < 8; k++) { result[resultNum][j][k] = board[j][k]; } } resultNum++; board[layer][i] = 0; } else { board[layer][i] = 1; queen(layer+1); board[layer][i] = 0; } } } return 0; }
这里需要明白一件事,当递归函数queen返回时意味着:
第layer层以下的所有摆放皇后位置的方法都已经尝试过一遍了!!!
所以每当我们检测到一个可行的皇后的位置时,所要做的就是将该位置为1,然后尝试该层以下所有摆放皇后的位置的方法。当递归函数执行完之后,我们就将刚找出的那个可行位置置为0,寻找下一个可行位置。
对于第一层,也就是X=0而言,全部的8个位置都是可行的,剩余的就是找出余下7层摆放皇后位置的方法。
当到达第八层,也就是X=7时,每找到一个可行位置,就意味着一个可行解的诞生,这里我们就将结果记录下来。
啊,全部说完了,也
4000
不知道我说明白解法没有。然后就是运行的主函数了,运行queen(0), 然后打印结果。
int main() { queen(0); for (int n = 0; n < resultNum; n++) { printf("-----------------------------\r\n"); for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { printf("%d ", result [i][j]); } printf("\r\n"); } } printf("the result:%d\r\n", resultNum); return 0; }
相关文章推荐
- 自己写的J2ME手机文件浏览器,个人感觉代码比书上的更能让人明白
- 关于B/S中代码分离的个人观点
- 个人学习代码保存:例4.在.net程序中使用事务处理
- 个人学习代码保存:例12.读取GridView文件中的数据到Excel文件
- 福林天下(jdlsfl)发起的代码分享的个人整理帖
- 水晶报表自定义参数传递个人示例代码
- 个人学习代码保存:例5.利用标准FileUpload单文件上传
- 个人学习代码保存:例9.在存储过程中使用cast 类型转换的实例
- 个人学习代码保存:例11.读取Excel文件中的数据
- 发送邮件成功率最高代码(转载,个人感觉不错)
- 个人随笔-20070621关键代码-2
- 个人学习代码保存:例1.asp.net DataList相关操作
- 个人学习代码保存:例3. GridView相关练习操作
- 网络应用系统---系统设计架构个人项目实战示例(各种页面代码A)
- 使用.net操作pcc的个人数据库代码
- 关于增加个人后台“恢复上次提交”和“插入代码”的公告
- 实用对称漂浮代码,个人站长拉广告的最爱
- 个人学习代码保存:例6.多文件上传
- 代码那些事儿---走出软件作坊:三五个人十来条枪 如何成为开发正规军(二十八)
- 关于jQuery插件jTip的修改,代码基本上没变,只进行了简单的修改,我个人认为这样更合适!