八皇后算法(回溯)

算法描述: 八皇后是一道很具典型性的题目。它的基本要求是这样的:在一个8*8的矩阵上面放置8个物体,一个矩阵点只允许放置一个物体,任意两个点不能在一行上,也不能在一列上,不能在一条左斜线上, 当然也不能在一条右斜线上。

八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。

算法分析:数组left,right,col分别用来标记冲突,

    col数组代表列冲突,从col[0]~col[7]代表第0列到第7列,如果某列上已经有皇后,则为1,否则为0;

  right数组代表主对角线冲突,为right[i-j+7],即从right[0]~right[14],如果某条主对角线上已经有皇后,则为1,否则为0;

  数组left代表从对角线冲突,为left[i+j],即从left[0]~left[14],如果某条从对角线上已经有皇后,则为1,否则为0;

1.初始化

int col[8]={0};
int left[15]={0};
int right[15]={0};
int Q[8];//皇后
int cnt=0;//计数器

2.输出函数

void Printf(){
	int a[8][8]={0};
	for(int k=0;k<8;++k){
		a[k][Q[k]]=1;
	}
	for(int k=0;k<8;++k){
		for(int m=0;m<8;++m){
			printf("%2d",a[k][m]);
		}
		printf("\n");
	}
	printf("\n\n");
}

3.Queue函数

void Queen(int i){
	int j;
	for(j=0;j<8;j++)
		{
			if((!col[j])&&(!left[j+i])&&(!right[7+i-j]))//如果该列、左对角线及右对角线没有皇后
			{
				Q[i]=j;										//放皇后
				col[j]=left[i+j]=right[7+i-j]=1;	//修改左右对角线的值
				if(i<7) Queen(i+1); //如果没放完,递归
				else Printf(),cnt++;   //回溯,求所有解
				col[j]=left[i+j]=right[7+i-j]=0;
		  }
	}	
}

4.下面放出完整代码

#include
#include

int col[8]={0};
int left[15]={0};
int right[15]={0};
int Q[8];
int cnt=0;
void Printf(){
	int a[8][8]={0};
	for(int k=0;k<8;++k){
		a[k][Q[k]]=1;
	}
	for(int k=0;k<8;++k){
		for(int m=0;m<8;++m){
			printf("%2d",a[k][m]);
		}
		printf("\n");
	}
	printf("\n\n");
}
void Queen(int i){
	int j;
	for(j=0;j<8;j++)
		{
			if((!col[j])&&(!left[j+i])&&(!right[7+i-j]))
			{
				Q[i]=j;										
				col[j]=left[i+j]=right[7+i-j]=1;	
				if(i<7) Queen(i+1);
				else Printf(),cnt++;
				col[j]=left[i+j]=right[7+i-j]=0;
		  }
	}	
}


int main(void){
	Queen(0);
	printf("一共有%d组解",cnt);

}

你可能感兴趣的:(数据结构)