N皇后&八皇后

N皇后

8皇后问题是在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

现在请你求在n*n的棋盘上摆放n个皇后的方案数。

输入格式

一行,一个正整数n ( n < 13)

输出格式

一行,一个整数,表示所求的方案数

输入样例

8

输出样例

92

我们先看八皇后问题
在8×8的棋盘上,放置8个皇后(棋子),使两两之间互不攻击。所谓互不攻击是说任何两个皇后都要满足:
(1)不在棋盘的同一行;
(2)不在棋盘的同一列;
(3)不在棋盘的同一对角线上。
因此可以推论出,棋盘共有8行,每行有且仅有一个皇后,故至多有8个皇后。这8个皇后每个应该放在哪一列上是解该题的任务。

  • 解题思路一 —— 回溯法**

1、定义Try( i )——试探放第 i 行上的皇后。
2、讨论将第 i 行上的皇后放在 j 列位置上的安全性。
我们可以逐行地放每一个皇后,因此,在做这一步时,假定第 i 行上还没有皇后,不会在行上遭到其它皇后的攻击。只考虑来自列和对角线的攻击。我们定义 q( i ) = j 表示第 i 行上的皇后放在第 j 列,一旦这样做了,就要考虑第 i 个皇后所在的列不安全了,这时让 C[ j ]= 0,同时,要考虑通过( i, j ) 位置的两条对角线也不安全了。分析看出从左上到右下的对角线上的每个位置都有 i – j = 常数 的特点;从左下到右上的对角线上的每个位置都有 i + j = 常数 的特点。比如两条对角线上的点,一条有 i - j = -1,一条有 i + j = 7 的特点。

在这里插入图片描述定义 int R[ 17 ]
R[ k ] k= 2,3,…,16
k = i + j
i = 1,2,…,8 j = 1,2,…,8
描述从右上至左下的对角线是否安全
数据类型为整型
1--------安全
0-------不安全

最优解:

#include <stdio.h>
#include <math.h>
void nqueen(int n);
int n;//皇后个数
int count=0;
int line[30]={0},right[40]={0},left[40]={0};
int main()
{
    scanf("%d",&n);
    nqueen(0);
    printf("%d",count);
    return 0;
}
void nqueen(int k){//k行
    int i=0;
    if(k==n){
        count++;
    }
    for(i=0;i<n;i++){//i列
        if(line[i]
                //该列不安全
                ||left[k+i]
                //右上到左下这条线不安全
                ||right[i-k+n])
            //左上到右下这条线不安全
            continue;
        else{
            line[i]=1;
            left[i+k]=1;
            right[i-k+n]=1;
            //置为不安全
            nqueen(k+1);
            line[i]=0;
            left[i+k]=0;
            right[i-k+n]=0;
            //回溯时置为安全
        }
    }
}
  • 解题思路二 ——扫描法
#include <stdio.h>
#include <math.h>
void nqueen(int n);
int n;//皇后个数
int queenpos[20];//第i行皇后所在的列
int count=0;
int main()
{
    scanf("%d",&n);
    nqueen(0);
    printf("%d",count);
    return 0;
}
void nqueen(int k){
    int i=0;
    if(k==n){
        count++;
    }
    for(i=0;i<n;i++){
        int j;
        for(j=0;j<k;j++){
            if(queenpos[j]==i||(queenpos[j]-j)==(i-k)||(queenpos[j]+j)==(i+k))
                break;
        }

        if(j==k){
            queenpos[k]=i;
            nqueen(k+1);
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值