八皇后问题(递归回溯)

本文探讨了八皇后问题的解决策略,重点在于理解如何运用递归回溯法。在实现过程中,作者强调了回溯的重要性,即在达到目标状态后清除原有位置的标记,以避免影响后续的危险判断。同时,文章还澄清了二维数组和二级指针的区别,指出二维数组名实际上是指向一维数组的指针,而非二级指针。
#include<stdio.h>
#include<stdlib.h>
int sum = 0;
int Danger(int r,int c, int(*a)[8]){
	for(int i=0;i<8;i++){
    	if(a[i][c])
      	return 0;
    }
 	for(int i=r,j=c;i>=0&&j>=0;i--,j--){
     	if(a[i][j])
     	return 0;
   }
    for(int i=r,j=c;i>=0&&j<8;i--,j++){
    	if(a[i][j])
    	return 0;
   }
    return 1;
}
/*int Danger(int row, int j, int(*chess)[8]){
	int flag1 = 1, flag2 = 1, flag3 = 1, flag4 = 1, flag5 = 1;
	int ia, ib = 1, ic = 1, id = 1, ie = 1;
	for(ia = 0; ia < 8; ia++){
		if(*(*(chess + ia) + j) == 1){
			flag1 = 0;
			break;
		}else flag1 = 1;
	}
	
	while((row - ib) != -1 && (j - ib) != -1){
		if(*(*(chess + row - ib) + j - ib) == 1){
			flag2 = 0;
			break;
		}else flag2 = 1;
		ib++;
	}
	
	while((row + ic) != 8 && (j - ic) != -1){
		if(*(*(chess + row + ic) + j - ic) == 1){
			flag3 = 0;
			break;
		}else flag3 = 1;
		ic++;
	}
	
	while((row - id) != -1 && (j + id) != 8){
		if(*(*(chess + row - id) + j + id) == 1){
			flag4 = 0;
		}else flag4 = 1;
		id++;
	}
	
	while((row + ie) != 8 && (j + ie) != 8){
		if(*(*(chess + row + ie) + j + ie) == 1){
			flag5 = 0;
			break;
		}else flag5 = 1;
		ie++;
	}
/*	printf("%d", flag1);
	printf("%d", flag2);
	printf("%d", flag3);
	printf("%d", flag4);
	printf("%d", flag5);
	printf("\n");*/
	//printf("/");
/*	if(flag1 && flag2 && flag3 && flag4 && flag5){
		return 1;
	}else return 0;
} */
void EQ(int row, int col, int(*chess)[8]){
/*	int chess[8][8];
	for(int i = 0; i < 8; i++){
		for(int j = 0; j < 8; j++){
			chess[i][j] = pchess[i][j];
		}
	}*/
	if(row == 8){
		for(int i = 0; i < 8; i++){
			for(int j = 0; j < 8; j++){
				printf("%d ", *(*(chess + i) + j));
			}
					printf("\n");
		}
		printf("\n");
		++sum;
		return;
	}
	for(int j = 0; j < 8; j++ ){
		if(Danger(row, j, chess) == 1){
			*(*(chess + row) + j) = 1;
			EQ(row + 1, col, chess);
			*(*(chess + row) + j) = 0;
				/*	for(int i = 0; i < 8; i++){
					*(*(chess + row ) + i) = 0;
				}
				continue;*/
		}
		
	}
	
}

int main(){
	int chess[8][8];
	for(int i = 0; i < 8; i++){
		for(int j = 0; j < 8; j++){
			chess[i][j] = 0;
		}
	}
	EQ(0, 8, chess);
	printf("%d", sum);
	return 0;
}

第一次代码实现的时候,主体逻辑没有考虑清楚,只循环了一轮就输出了,问题在于没有回溯。

for(int j = 0; j < 8; j++ ){
		if(Danger(row, j, chess) == 1){
			*(*(chess + row) + j) = 1;
			EQ(row + 1, col, chess);
			*(*(chess + row) + j) = 0;

回溯

递归到最末行,成功输出后,要抹去原来的位置痕迹。否则会影响Danger函数的判断

*(*(chess + row) + j) = 0;

二维数组和二级指针

第一次代码实现的时候,用二级指针指向二维数组名,出现报错。
因为这两个概念完全不等价,二维数组名不是一个二级指针。
二维数组名是指向一维数组的指针,是一个一级指针 int(*chess)[8]
同理三维数组名是指向二维数组的指针,也是一个一级指针。
多维数组名其实就是一个指向维度-1的数组指针(int(*a)[x][x][x]…)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值