八皇后

        在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即随意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

       结题思想:先给第一列的皇后一位置,依据规则。然后确定第二行皇后位置。以此类推,确定其余每列的皇后的位置。得出问题的解

         给棋盘设置一个二维数组chess[8][8],所有初始化为0。找到每一列中合适的位置并赋为1。而确定列中元素的位置没有确定行中元素位置方便。

能够转化为求解每行中这种一个合适位置。找到则进行下一行的寻找,直到行数为8时递归结束获得问题的解。

         定义两个函数EightQueen(row,n,chess)用于递归调用下一行的推断、safePosition(row,n,chess)用于需找安全的位置。即元素所在行、列及左右两条对角线上都不能有皇后存在。

代码例如以下:

#include <stdio.h>
int count;//全局变量记录有多少种 
int safePositon(int row, int n, int (*chess)[8])
{
	int i,j,flag1=0,flag2=0,flag3=0,flag4=0,flag5=0;
	
	//推断列方向
	for(i=0; i<8; i++)
	{
		if(*(*(chess+i)+n) !=0)
		{
			flag1=1;
			break;
		}
	}
	//推断左上方 
	for(i=row, j=n; i >= 0 && j >= 0; i--, j--)
	{
		if(*(*(chess+i)+j) !=0)
		{
			flag2=1;
			break;
		}
	} 
	//推断右下方 
	for(i=row, j=n; i<8 && j<8; i++, j++)
	{
		if(*(*(chess+i)+j) !=0)
		{
			flag3=1;
			break;
		}
	}
	//推断右上方 
	for(i=row, j=n; i >=0 && j<8; i--, j++)
	{
		if(*(*(chess+i)+j) !=0)
		{
			flag4=1;
			break;
		}
	}
	//推断左下方 
	for(i=row, j=n; i<8 && j >= 0; i++, j--)
	{
		if(*(*(chess+i)+j) !=0)
		{
			flag5=1;
			break;
		}
	}
	if(flag1 || flag2 || flag3 || flag4 || flag5)
	{
		return 0;
	}
	else
	{
		return 1;
	}        
}
void EightQueen(int row, int n, int (*chess)[8])
{
	//row表示行,j表示列。(*chess)[8]表示指向棋盘每一行的指针;一行一行的递归 
	int chess2[8][8],i,j;
	for(i=0; i<n; i++)
	{
		for(j=0; j<n; j++)
		{
			chess2[i][j]=chess[i][j];
		}
	}
	if(row == 8)//递归的结束条件 
	{
		count++;
		printf("第%d种
",count);
		for(i=0; i<8; i++)
		{
			for(j=0; j<8; j++)
			{
				printf("%d ",*(*(chess2+i)+j));
			}
			printf("
");
		}
	} 	
	else
	{
		for(j=0; j<8; j++)
		{
			if(safePositon(row, j, chess))
			{
				for(i=0; i<8; i++)
					*(*(chess2+row)+i)=0;
				*(*(chess2+row)+j)=1;
				
				EightQueen(row+1, n, chess2);
			}
			
		}
	}
}
int main(void)
{
	int i,j,chess[8][8];
	if(freopen("D:\OUTPUT.txt","w",stdout)==NULL)
		fprintf(stderr,"errorredirectingstdout
");
	for(i=0; i<8; i++)
	{
		for(j=0; j<8; j++)
		{
			chess[i][j]=0;//棋盘的初始化 
		}
	}
	
	EightQueen(0, 8, chess); 
	
	printf("一共同拥有%d种 
",count);
	
	fclose(stdout);
}
       因为生成结果多。控制台的缓存不足以显示全部结果。

在这里用freopen("D:\OUTPUT.txt","w",stdout)==NULL将stdout重定向到文件里保存。

若要又一次将输出重定向到控制台。能够调用stream=freopen("CON","w",stdout);(stream是一个文件指针)


原文地址:https://www.cnblogs.com/gavanwanggw/p/7217168.html