ACM—N皇后问题

来源:互联网 发布:计量分析软件 编辑:程序博客网 时间:2024/05/18 00:00

一、题目

    在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 15int 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 15int 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
原创粉丝点击