八皇后问题 递归回溯思想 (递归分治篇)------- 算法笔记017

基本概念

在这里插入图片描述

编程思想

对于这样一个问题我们首先想是要创建一个8x8格式的棋盘,我们用二维数组去实现,数组中的每个值初始化为0,用值1表示这个地方已经放了棋子。这样我们每一行都用一个1来表示放了一个棋子。
问题的关键在于递归回溯,和判断某一位置是否这一放置棋子。当我们在某一位置想要放置棋子时我们要先判断这个位置是否和上面的棋子在同一条线上,如果不在同一条线上就标志1,如果在就向后一个位置判断,假如整行都不符合条件那就向上回溯了,到了上面一行我们将标志位向后移动一位继续开始向下的递归。

代码解读

代码共有三个函数组成:print()打印棋盘,check()判断是否满足条件,EightQueen()算法总函数。
对于算法的复杂度分析:
由于算法是会回溯的它会尝试每种情况
最多的情况有 8 * 8 * 8 * 8 * 8 * 8 * 8 * 8 即 8^8
程序会最多尝试8^8次数
算法复杂度为:O(n^8)

typedef int Status;

int count;//共有多少种放置方法
int a[8][8];//棋盘


//打印二位棋盘
void print(){
	int i,j;
	printf("第%d方案",count);
	printf("\n\n");
	for(i=0;i<8;i++){
		for(j=0;j<8;j++){
			
			printf("%d ",a[i][j]);
			
		} 
		printf("\n");
		 
	}
	
}

Status check(int r,int c){
	//r: 行标志
	//c: 列标志

	int index;
	//遍历行,检查这个位置的垂直方向
	for(index=0;index<r;index++){
		//如果检测到垂直方向有了放置的棋子,返回0
		if(a[index][c]){
			return 0;
		}
	}
	
	int k,j;
	//检测左上斜线
	for(k=r-1,j=c-1;k>=0&&j>=0;k--,j--){
		if(a[k][j]){
			return 0;
		}
	}
	
	//检测右上斜线
	for(k=r-1,j=c+1;k>=0&&j<=7;k--,j++){
		if(a[k][j]){
			return 0;
		}
	}
	
	//如果都满足条件,返回1
	return 1;
}

void  EightQueen(int row){
	//row的作用:递归每一行
	//当row为8时即超出数组行标数,说明一种情况产生,打印返回

	if(row==8){
		count++;//有多少种情况
		print();//打印棋盘
		return; 
	}	

	int c;
	//遍历每一列
	for(c=0;c<8;c++){
		//如果满足放置条件
		if(check(row,c)){
			
			a[row][c]=1;
			//进行下一行的判断
			EightQueen(row+1);

			//回溯:当递归返回时说明下一行不满足放置条件

			//将此位置0,也就是拿走棋子,向下一个满足条件的位置放置
			a[row][c]=0;			
			
		}
		
		
	}
	
	
}

执行结果

在这里插入图片描述在这里插入图片描述

由此可见八皇后问题共有92种解法
对此我们可以延伸出N皇后的问题
不过主要还是对于递归和回溯思想的应用

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智者_若愚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值