学习这种经典问题的一个好处就是网上讨论这个问题的文章铺天盖地,一点儿也不担心缺少可以参照的代码和详细的思路。
个人真觉得N皇后问题真把递归玩出花来了。这道题必须打表,测试数据的数量好像非常大,如果输入一组计算一组,那铁定是要超时的。
首先对于第一个皇后,分别将它放在1~n列,根据这个皇后放的位置,找出下一个皇后放在哪些位置是合法的。对于第x个皇后,如果放在第i列是合法的,就在这种情况的基础上去放下一个皇后。需要注意的是,第x个皇后放在第i列合法不是说皇后必须放在第i列,实际上这只是合法情况的一种,它也可以放在任意其他符合条件的列,对于那些列,也会有不同的后续的皇后的放置方法。关于这种放置方法最终是否合法,都需要到第n个皇后放置后才能确定。
关于算法,对照着代码理解吧,直接讲的话感觉不太好讲清楚。
#include<stdio.h>
#include<cmath>
#define N 15
int n,ans,sum;
int a[N],b[N];
int judge(int x)
{
int i;
for(i=1;i<x;i++)
{
if(b[x]==b[i]||abs(x-i)==abs(b[x]-b[i]))//判断是不是在同一列或者对角线上。
return 0;
}
return 1;
}
int queen(int x)
{
int i;
if(x>n)
sum++;//如果已经递归到要放第n+1个皇后了,那就说明这种放置方式的前n个皇后是符合条件的,sum++。
else
{
for(i=1;i<=n;i++)
{
b[x]=i;//将第x的皇后放在第i列。
if(judge(x))//如果放在这一列没有问题的话,就继续放下一个皇后。
queen(x+1);
}
}
return sum;
}
int main()
{
int i;
for(i=1;i<=10;i++)//打表,测试数据太大,如果不打表会超时。
{
n=i;
sum=0;
ans=queen(1);//从1开始递归。
a[i]=ans;
}
while(scanf("%d",&n),n)
printf("%d\n",a[n]);
return 0;
}