N皇后问题(非递归回溯)

简单说明一下N皇后的解决思路。

1.初始化棋盘,即建立一个一维数组,储存一个初值(不是0到N-1就行);

2.寻找N皇后:a.判断皇后是否可以放置...而要想让皇后可以被放置,就必须满足皇后与皇后之间没有行冲突,列冲突,对角线冲突。那么首先想到的思路就是将你放置在该行该列的皇后与前面已经放置的皇后进行冲突检测,只要有一个冲突了,则该皇后就不能被放置。

                        b.回溯...如果该皇后不能在当前行当前列放置,则应该将该皇后往后移,直到当前行的所有列都检测完了,还不能放置皇后的话,就应该回溯到上一行,将上一行的皇后往后移,如果后移的皇后不能放置的话,继续回溯,直到可以被放置。一旦放置成功就顺推,直到最后一行。

                        c.结束...当顺推到最后一行时,回溯从最后一行开始,逐步将每一行的所有列都进行检测,直到回溯到第一行,则说明已经找到所有解。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

#define Queen 8
#define CHUZHI -1

int a[Queen];
void init(){//第一步完成棋盘的初始化
	int *p;
	for(p=a;p<a+Queen;++p)
		*p=CHUZHI;
}

int valid(int row,int col){//判断皇后是否可以放置
	for(int i=0;i<=row;i++) //检测前row行,不必每次检测Queen行
		if(a[i]==col||abs(a[i]-col)==abs(row-i))//判断行冲突和列冲突
			return 0;
	return 1;
}

void print(){ //规范打印出N皇后位置
	for(int i=0;i<Queen;i++){
		for(int j=0;j<Queen;j++)
			if(a[i]!=j)
				printf("%c ",'.');
			else
				printf("%c ",'#');
		printf("\n");
	}
	for(i=0;i<Queen;i++)
		printf("%d ",a[i]);
	printf("\n");
	printf("--------------------------------------\n");
	
}

void queen(){//寻找N皇后
	int n=0;
	int i=0,j=0;
	while(i<Queen){
		while(j<Queen){
			if(valid(i,j)){ //能放置皇后,进入if
				a[i]=j; // 储存第I行的第j列位置的皇后(每行有且只有一个皇后)
				j=0;  //将j置零,以便于下一行从第一列检测
				break;//这一行找到皇后,立马跳出第二层循环,到下一行检测
			}
			else//不能放置皇后,则将这一行的皇后往后移一列
				++j;
		}
		if(a[i]==CHUZHI){ //如果这一行没有位置能放置皇后的话,进入If
			if(i==0)   //如果被回溯到第一行,说明已经找到了所有的解,
				break;//跳出循环,结束程序
			else{
			--i;  //否则,回溯到上一行
			j=a[i]+1;//将上一行皇后的位置往后移
			a[i]=CHUZHI;//原来位置置为初值
			continue;//跳过下面代码部分,直接进入下一次循环
			}
		}
		if(i==Queen-1){
			printf("找到第%d组解\n",++n); //已经找到一组解
			print();//还没完,我们要找到所有的解,所以要把这一行的每一列都遍历
			j=a[i]+1;//这一行的皇后位置往后移
			a[i]=CHUZHI;//原来位置置为初值
			continue;//跳过下面代码部分,直接进入下一次循环
		}
		++i;
	}
		
}
int main(void){
	init();
	queen();
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41048982/article/details/88777832