C语言实现数据结构之八皇后求解

任务

国际西洋棋棋手马克斯·贝瑟尔于1848年提出在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。请设计算法编写程序解决。

分析

从第一行开始,当某一行皇后位置不与前面所有皇后位置冲突,那么记录该行皇后位置并调用递归函数进入下一行,摆放下一个皇后,逐个位置摆放,若该行所有位置都被其他皇后占领,那么就回溯到上一行重新摆放上一行皇后,直至所有皇后都不冲突。那么记录一次方法然后回溯寻找其他摆放方法。(回溯与递归算法)

流程图

存储结构设计
int place[8]={0};								/*皇后位置*/
bool flag[8]={1,1,1,1,1,1,1,1};					/*定义列*/
/*共有15个对角线,因此定义一个长度为15的bool型数组,
初值为1代表该对角线没有被皇后占领,若被皇后占领则赋值为0*/
bool d1[15]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};	/*定义上对角线*/
bool d2[15]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} ;	/*定义下对角线*/
int number=0;									/*记录解的个数*/
源代码
/*八皇后问题:求解并输出八皇后的所有解(92个解)*/
#include<stdio.h>
typedef int bool;
#define false 0
#define true 1

int place[8]={0};								/*皇后位置*/
bool flag[8]={1,1,1,1,1,1,1,1};					/*定义列*/
/*共有15个对角线,因此定义一个长度为15的bool型数组,
初值为1代表该对角线没有被皇后占领,若被皇后占领则赋值为0*/
bool d1[15]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};	/*定义上对角线*/
bool d2[15]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} ;	/*定义下对角线*/

int number=0;									/*记录解的个数*/

/*定义输出函数*/
void print(){
	int col, i, j;
	number++;					/*每调用一次输出函数number自加一次,记录解的个数*/
	printf("No.%2d\n", number);
	int table[8][8]={0};		/*设置一个8*8的棋盘*/
	for (i=0;i<8;i++)
		table[i][place[i]]=1;	/*将每一行皇后所在位置赋值为1*/

	for (i=0;i<8;i++){
		for (j=0;j<8;j++)
			printf("%d|",table[i][j]);
		printf("\n");
	}
}
/*定义递归回溯函数*/
int queen(int n){
	int col;
	for (col = 0; col < 8; col++){
		if (flag[col] && d1[n-col+7] && d2[n+col]){ /*判断皇后是否冲突*/
			place[n] = col;							/*放置皇后*/
			/*将该皇后所在的行、列、对角线设置为被占领*/
			flag[col] = false;
			d1[n-col+7] = false;
			d2[n+col] = false;
			if(n<7)	
				queen(n+1);	/*当行数小于7时;递归调用下一行*/
			else
				print();	/*调用输出函数*/
				
			flag[col]=true;	/*回溯*/
			d1[n-col+7]=true;
			d2[n+col]=true;
		}
	}
	return number;
}

int main()
{
	number = queen(0);					/*从第0行开始执行*/
	printf("共有%d种摆放方法", number);
	
	return 0;
}
运行结果

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值