Bootstrap

N皇后问题 回溯法详解----第一篇博客希望多多支持

原题:

N皇后问题

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

Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。

Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。

Sample Input
1
8
5
0

Sample Output
1
92
10

题解:

思路就不说了,大致就是找到皇后们处于同一列和斜线上时的条件 (重中之重)
我们是一行一行的放置皇后,所以不需要判断行冲突。判断列冲突很简单,直接和前面的比一下是否一样即可,而对于对角线冲突,就有一个特殊的小技巧:由于每一条主对角线(x-y)是一定的,每一条副对角线(x+y)是一定的。于是,我们通过判断那些定值与前面已经放置的皇后的定值比较即可判断是否冲突。假设我们把第x个皇后放在了第size[x]列,那么之需要判断前x-1个皇后是否与她冲突即可。

#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
int N,cot;    //分别代表棋盘尺寸(皇后数量)和皇后可能成功摆放的结果总数
int size[11];//数组的下标表示行,对应的值表示列
int ans[11]; // 用于打表存放结果
void dfs(int n)
{
    int flag;
    if(n==N+1)  //当 最后一个皇后成功放置时返回.
    {
        cot++;   //成功的次数加一
        return ;
    }
    for(int i=1;i<=N;i++)
    {
        size[n]=i;   //代表将第一个皇后放置在第1行第i列(或者说第n个皇后)
        flag=1;      //放完之后就行标记
        for(int j=1;j<n;j++)  //这个for循环用来检测 这个皇后的位置和之前的n个皇后的位置是否冲突
        {
            if(size[j]==i||((abs(n-j))==abs(size[j]-i)))
            {
                flag=0;
                break;
            }
        }
        if(flag) dfs(n+1);   // 如果放置在第i列不冲突 则开始放下一个皇后   如果冲突 放在下一列继续判断
    }

}
int main()
{
    for( N=1;N<=11;N++)//因为本题时间限制,所以需要先打表
    {
        cot=0;    //临时存放结果
        dfs(1);
        ans[N]=cot;  // 将结果依次放入表中
    }
    while(cin >>N)
    {
        if(!N) break;
        cout <<ans[N]<<endl;
    }
    return 0;
}

第一次写题解 ,,,,,, 超级激动 哈哈哈 ,以后就养成写题解的好习惯,勉励自己使自己进步,期待暑假的集训,不要做小白!!!!

;