深搜之N皇后问题

深度优先搜素(Depth First Serch):

其过程简而言之是对每一个分支路径深入到不能再深入位置,即沿一条路径不断的纵深,不撞南墙不回头。
这里写图片描述
也就是加入我们要寻找8这个数字,首先,它会9->7->6->3一直到最后一个,发现并没有寻找到8,那么我们再返回3->6,还是没有8,我们继续返回3->6->7,发现7还有一个岔路,那么我们就从7->8,这样即完成了寻找。


深搜之N皇后问题:

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

Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
题目分析: 首先任意皇后不能处于同一行,同一列,主副对角线上,那么也就是说我们每一行是只能是一个皇后的。那我们就固定行,从第一行之第N行,逐列寻找满足条件的位置去放上皇后即可了。但是这条题必须得打表,也就是说必须把1~10的行的可能放置种类都存在数组当中,因为如果测试样例是 10 10 10…你没有必要每次算一遍,所以存在数组当中,直接调用就行。

/*
对于皇后问题这道题,要明白是不能在同一列同一行放皇后,也就是说
一行只能有一个皇后,固定行数之后只要对列遍历即可。
*/
#include <bits/stdc++.h>

using namespace std;

int mark[11][11];//我们从第一行第一列开始,这是标记
int cnt[11];//打表计数
int N;//棋盘和皇后的数量
int Count;
void dfs(int row);
bool isCorrect(int R,int C);

int main(){
    //我们将棋盘由1~10的所有所有可能的存在打表的数组当中
    for(N=1;N<=10;N++){
        dfs(1);//从第一行开始
        cnt[N]=Count;
        Count=0;
    }
    while(~scanf("%d",&N)&&N){
        cout << cnt[N] <<endl;
    }
    return 0;
}
void dfs(int row){
    if(row==N+1){
        Count++;//也就是前1~N行,每个位置都正确的放入了皇后,那么次数就+1
        return;
    }
    else{
        //循环的意思是,我们已知行是row行了,
        //那么我们只需要从第一列到第N列中选择正确的一列即可
        for(int i=1;i<=N;i++){
            if(isCorrect(row,i)){
                mark[row][i]=1;//如果这个位置可以放置皇后,那么我们把它标记为1
                dfs(row+1);//之后进行下一行的搜索,
                           //dfs会一直纵深,直到停止,return
                mark[row][i]=0;
                //当dfs return返回后,说明这一条支路已经走完,
                //那么我们把此位置标记为0,进行下一个可能性的判断
                //每次深搜之后整个mark数组都会重新归为0
            }
        }
    }
    return;
}
bool isCorrect(int R,int C){
    /*
    我们将前1~R行,进行遍历,看是否满足条件,因为R~N行,并没有放任何皇后
    那么他们本身就是满足条件的
    */
    for(int i=1;i<=R;i++){
        for(int j=1;j<=N;j++){
            if(i+j==R+C&&mark[i][j]==1)return false;//在主对角线上,满足规律i+j=R+C
            if(C-R==j-i&&mark[i][j]==1)return false;//在副对角线上
            //在同一列当中
            if(j==C&&mark[i][j]==1)return false;
        }
    }
    return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值