八皇后问题 及 非正式个人代码

来源:互联网 发布:量子化学软件 编辑:程序博客网 时间:2024/05/08 16:23

昨天有师兄因为做对了一道八皇后,(当然不止这一道题,一共有三道题),拿到的华为的Special offer,想着这个问题很多年前我也写过。(本人目前研二),晚上闲着无聊就来写写。


八皇后问题描述

皇后问题,是一个古老而著名的问题,是回溯算法典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于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 92int 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时,每找到一个可行位置,就意味着一个可行解的诞生,这里我们就将结果记录下来。

啊,全部说完了,也不知道我说明白解法没有。然后就是运行的主函数了,运行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[n][i][j]);}printf("\r\n");}}printf("the result:%d\r\n", resultNum);    return 0;}


0 0
原创粉丝点击