递归算法之“八皇后问题”

这篇博客探讨了八皇后问题,即在8x8棋盘上放置八个皇后,确保它们互不攻击。文章解释了如何使用二维数组表示棋盘,通过判断斜线和同行的安全性来确定皇后位置,并通过递归算法实现解决方案。文中提供了具体的代码实现,并展示了一部分执行结果,找到92种不同的解决方案。
摘要由CSDN通过智能技术生成

一、八皇后问题

      八皇后问题:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

下面的图片为八皇后问题的一种解法:

二、实现

在编写这个程序之前,我们先来思考几个问题:

1.棋盘怎么表达?

答:用二维数组来表示,并且,1表示有皇后,0表示无皇后。

2.如何判断当前位置(行、列)是安全的?

答:分别判断左上方斜线、正上方以及右上方斜线有无皇后。

3.第一行、第二行...第i行...第八行,皇后的摆放方法(程序)是否相同?

答:相同。

4.对于每一行,需要尝试每一个位置(列),判断其安全性。若安全,则继续下一行(递归)。

5.若本行的所有位置都尝试过了(无论成功与否),都要返回到上一行,继续尝试上一行未尝试完的位置(列)。

6.何时算找到一个解?

答:当尝试到第九行时,就找到了一个解,即:前八行各存在一个互不冲突的皇后。

下面给出具体实现的代码:

#include <stdio.h>

#include "mec.h"

#define WIDTH 8

boolean isSafe(boolean (*chessBoard)[WIDTH],int row,int col);
void showChess(boolean (*chessBoard)[WIDTH]);
void chess(boolean (*chessBoard)[WIDTH],int row);

void chess(boolean (*chessBoard)[WIDTH],int row){
	int col;
	
	if(row >= WIDTH){
		showChess(chessBoard);
		return;
	}
	
	for(col = 0;col < WIDTH;col ++){
		if(isSafe(chessBoard,row,col)){
			chessBoard[row][col] = TRUE;
			chess(chessBoard,row + 1);
			chessBoard[row][col] = FALSE;
		}
	}
	
}

void showChess(boolean (*chessBoard)[WIDTH]){
	int row;
	int col;
	static int count = 0;
	
	printf("第%d个:\n",++count);
	for(row = 0;row < WIDTH; row++){
		for(col = 0;col < WIDTH; col++){
			printf("%5d",chessBoard[row][col]);
		}
		printf("\n");
	}
}

boolean isSafe(boolean (*chessBoard)[WIDTH],int row,int col){
	int i;
	int j;
	
	for(i = row - 1,j = col - 1;i >= 0 && j >= 0;i--,j--){
		if(chessBoard[i][j] == 1){
			return FALSE;
		}
	}
	
	for(i = row - 1,j = col;i >= 0;i --){
		if(chessBoard[i][j] == 1){
			return FALSE;
		}
	}
	
	for(i = row - 1,j = col + 1;i >= 0 && j < WIDTH;i--,j++ ){
		if(chessBoard[i][j] == 1){
			return FALSE;
		}
	}
	
	return TRUE;
}

int main(){
	boolean chessBoard[WIDTH][WIDTH] = {0};
	
	chess(chessBoard,0);
	
	return 0;
}

代码执行部分结果如下(输出了92个解):

 

以上说法若有不足之处,还请指点!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值