关闭

ACM—N皇后问题

140人阅读 评论(0) 收藏 举报
分类:

一、题目

    在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<stdio.h>
#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<stdio.h>
#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<n,则继续检测下一行t++
   {
    t++;
    x[t] = 0;
   }
  else   //到了这步说明,t行没有符合条件的,则让t--返回上一层
   t--;
 }
}

int main()
{
 scanf("%d",&n);
 search();
 printf("%d\n",sum);
 return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:9345次
    • 积分:382
    • 等级:
    • 排名:千里之外
    • 原创:29篇
    • 转载:5篇
    • 译文:0篇
    • 评论:1条
    文章分类
    最新评论