ACM—N皇后问题

一、题目

    在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于再n×n的棋盘上放置n个皇后,任何2个皇后不妨在同一行或同一列或同一斜线上。
输入
    给定棋盘的大小n (n ≤ 13)
输出
    输出有多少种放置方法。

二、思路

       首先,选择用什么样的方式来找出所有可能的情况,本题应采用固定行移动列的方式,用一个数组x[t] 来存放第t行放置的皇后的列号。

       然后,就该考虑什么样的属于合法放置,题目规定,不同行不同列不同对角线,由于是按行来找的,所以不同行的情况已经被排除在外,不同列只需保证x[t]!=x[i](i从1到t-1),不同对角线:①观察主对角线可知:行号-列号为一个固定值②观察副对角线可知:行号+列号为一个固定值。因此只需保证t-x[t]!=i-x[i]&&t-x[t]!=i-x[i](i从1到t-1)即可。

       最后,确保遍历到所有可能的情况,深度优先搜索。有两种办法:

      (1)运用递归

               写一个递归函数search,当满足条件是就调用自身。

      (2)不用递归

三、代码

(1)运用递归

#include
#define N 15
int n;
int x[N];
int sum = 0;

int check(int t)
{
 int i;
 for(i = 1;i < t;i++)
  if(x[t] == x[i]||t - x[t] == i - x[i]||t + x[t] == i + x[i])  //检查是否合法
   return 0;
 return 1;
}

void search(cur)
{
 int i;
 if(cur > n && n > 0)   //当行号超过n时,说明满足了条件,总情况数+1
  sum++;
 for(i = 1;i <= n;i++)
 {
  x[cur] = i;
  if(check(cur))
   search(cur + 1);  //当满足check函数时,递归调用自身。
 }
}

int main()
{
 scanf("%d",&n);
 search(1);   //从第一行开始检测
 printf("%d\n",sum);
 return 0;
}
(2)不用递归

#include
#define N 15
int n;
int x[N];
int sum = 0;

int check(int t)
{
 int i;
 for(i = 1;i < t;i++)
  if(x[t] == x[i]||i - x[i] == t - x[t]||i + x[i] == t + x[t])   //检查是否合法(不同行,不同列,不同对角线)
   return 0;
 return 1;
}

void search()
{
 int t = 1;
 x[1] = 0;
 while(t>0)
 {
  x[t]++;
  while(x[t] <= n && !check(t))  //当不满足条件时,列号+1
   x[t]++;
  if(x[t] <= n)   //当上个循环结束时,如果x[t]<=n说明,t行满足check函数
   if(t == n)   //若t=n,则说明有符合条件的格局,总情况数+1
    sum++;
   else   //若t


你可能感兴趣的:(ACM)