N皇后问题 HDU - 2553 深搜

原题

在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。

Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。

Sample Input
1
8
5
0
Sample Output
1
92
10

代码

第一种解法(其实两种差不多)

#include <bits/stdc++.h>
using namespace std;
int n,k, p[9999999], hash_[9999999],sum;
void queen(int ordinal){
    if (ordinal == n + 1){
        sum++;
        return;
    }
    else{
        for (int x = 1; x <= n; x++){
            bool flag = true;
            if (!hash_[x]){
                for (int pre = 1; pre < ordinal; pre++){
                    if (abs(ordinal - pre) == abs(x - p[pre])){
                        flag = false;
                        break;
                    }
                }
                if (flag){
                    hash_[x] = 1;
                    p[ordinal] = x;
                    queen(ordinal + 1);
                    hash_[x] = 0;
                }
            }
        }
    }
}

int main()
{
    int a[10];
    for(int i=0;i<10;i++){
        sum=0;
        n=i+1;
        queen(1);
        a[i]=sum;
    }
    while(cin>>k,k)
        cout<<a[k-1]<<endl;
}

第二种解法

#include <bits/stdc++.h>
using namespace std;
int cnt,col[11],n; //cnt用来数当前 n*n 宫格所得的解的数目,col临时记录被占了的格子,n为输入的宫格边长
bool check(int column,int row){ //判断是否满足占格条件
    for(int i=0;i<row;i++){ //遍历所有行,判断是否有打破规则的占格
        if(col[i]==column||(abs(col[i]-column)==abs(i-row)))
            //由于col是存放第 i 行被占用的列的下标,所以col[i]==column就表示这列已经被占了,不满足规定,需要重新选择列
            //abs(col[i]-column)==abs(i-row)是判断是否在同一对角线的(两个列下标相减等于两个行下标相减),自行画图理解
            return false;
    }
    return true;
}
void queen(int r){
    if(r==n){ //如果达到最大行,获得一个解(因为如果某个解不可行是无法走到最大行的)
        cnt++; //解的数目增加
        return;
    }
    for(int column=0;column<n;column++){ //对列单独遍历
        if(check(column,r)){ //判断当前坐标是否符合“与其他棋子不同行不同列”,“与其他棋子不同对角线”的规定
            col[r]=column; //如果符合要求,那么就将当前行坐标对应的列坐标存入col里面(即存放棋子占用的格子的坐标)
            queen(r+1); //由于当前行已选择了一列占格,此时需要看看下一行满足条件的列
        }
    }
}

int main(){
    int save[10]; //存放十以内 n*n宫格的解的个数
    for(int i=0;i<=10;i++){
        cnt=0; //初始化
        memset(col,0,sizeof(col)); //初始化col数组
        n=i; //计算 1-10 的解数
        queen(0); //深搜
        save[i]=cnt;
    }
    while(cin>>n,n){
        cout<<save[n]<<endl;
    }
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值