算法学习记录 N皇后问题 递归解法

N皇后问题。 在一个N*N国际象棋盘上,

有N个皇后,每个皇后各占一格:要求

皇后间不会出现互相“攻击”的现象。

即不能有两个皇后处在同一行,同一列

或同一对角线上。问 共有多少种不同的方法。

(N是一个大于等于2并且小于等于100的整数)

  思路:可以建立以个一维数组来储存N*N棋盘的行,这样的话,当把一个皇后放入棋盘,再把另一个皇后放入棋盘

  讨论其是否满足要求的时候,行冲突的问题就解决了,列冲突的话,只需要看map[i]中是否存在相应的列,做出相应

  操作;对于对角线判断,从草稿纸上可知,存在对角线冲突的两个皇后的 行列 之间的差的绝对值是相等的,所以,

  判断一个位置上是否可以放置皇后的问题得到解决。

#include "stdio.h"
#include "math.h"  

const int N = 100;            //最多放置皇后个数
int map[N];                    //存放皇后所在的行号
int count = 0;               //存放解的个数

void Print(int n)            //输出解
{
	int i;
	count++;
	printf("第%d 个解" , count);
	for(i=1; i<=n; i++)
		printf("(%d,%d)",i,map[i]);
	printf("\n");
}

int isPlace(int i, int k)                     //测试第k列的i行上能否摆放皇后
{
	int j;
	for(j=1 ; j < k ; j++)                           //j=1到k-1是已经旋转了皇后的列
	{
		if((map[j]==i) || (abs(map[j]-i)==abs(j-k)))//第j列皇后是否在i行上。位置(map[j],j)与(i,k)是否同对角线
			return 0;
	}
	return 1;
}

void Queens(int k, int n)             
{
	int i;
	if(k>n)
		Print(n);                          //所有皇后放置结束
	else
		for(i=1; i<=n; i++)            //在第k列上穷举每一个位置
			if(isPlace(i, k))//此处进行了图的旋转,判断k列中所有的位置,查看是否有可以放置皇后的位置//
			{
				map[k] = i;// 若有,则进行记录 map的下标为行  储存元素为列//
				Queens(k+1, n);            //放置余下的皇后
			}
}

void main()
{
	int n;                                 //n存放实际皇后个数
	printf("皇后问题(n<=100):");
	scanf("%d",&n);
	if(n>99)
		printf("n的值太大,不能求解\n");
	else
	{
		printf("皇后问题求解如下:\n");
		Queens(1,n);
	}
}

点赞