N皇后问题---回溯法

问题描述
在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
N后问题等价于再n×n的棋盘上放置n个皇后,任何2个皇后不可以在同一行或同一列或同一斜线上。

输入:
给定棋盘的大小n (n ≤ 13)
输出:
输出有多少种放置方法。

解题思路:
要解决N皇后问题,其实就是要解决好怎么放置这n个皇后,每一个皇后与前面的所有皇后不能在同一行、同一列、同一对角线,在这里我们可以以行优先,就是说皇后的行号按顺序递增,只考虑第i个皇后放置在第i行的哪一列,所以在放置第i个皇后的时候,可以从第1列判断起,如果可以放置在第1个位置,则跳到下一行放置下一个皇后。如果不能,则跳到下一列…直到最后一列,如果最后一列也不能放置,则说明此时放置方法出错,则回到上一个皇后向之前放置的下一列重新放置。此即是回溯法的精髓所在。当第n个皇后放置成功后,即得到一个可行解,此时再回到上一个皇后重新放置寻找下一个可行解…如此后,即可找出一个n皇后问题的所有可行解。

//n皇后   回溯法   这里是将数组x模拟为二维数组,这里的列不会重复,只需要判定行和对角线是否会重复
class Queen
{
    friend int Nqueen(int n);//该类的友元函数
private:
//x[m]=n表示从第m列的从上往下数第n个元素,这个很重要,将一维的变为二维
    bool Place(int k)//该函数用来判断该皇后是否处于合适位置
    {
        for (int i = 0; i < k; ++i)
        {
            if ( (x[i] == x[k]) || (abs(x[i] - x[k]) == abs(i - k)))//如果插入的元素和之前已插入元素在同一行或者同一列,则不能插入,返回false
            {
                return false;
            }
        }
        return true;
    }
    void Backtrack(int i)
    {
        if (i == n)
        {
            for (int r = 0; r < n;++r)
            {
                for (int c = 0; c < n;++c)//按行打印
                {
                    if (x[c] == r)
                    {
                        cout << "Q" << " ";
                    }
                    else
                    {
                        cout << "#"<<" ";
                    }
                }
                cout << endl;
            }
            cout << endl;
            sum += 1;
        }
        else
        {
        //j=0  x[0],x[1],x[2],x[3]=0;每一列的第一行
            for (int j = 0; j < n; ++j)
            {
                x[i] = j;//按列放入
                if (Place(i))
                {
                    Backtrack(i+1);
                }
            }
        }
    }

    int n;//n后问题
    int *x;//数组名
    int sum;//皇后最多几种摆放
};
int Nqueen(int n)
{
    Queen Q;
    Q.n = n;
    Q.sum = 0;
    Q.x = new int[n];
    for (int i = 0; i < n; ++i) Q.x[i] = 0;//数组全置为0
    Q.Backtrack(0);//从第0列开始
    delete[]Q.x;
    return Q.sum;
}
void main()
{
    int sum;
    int n;
    cin >> n;
    sum = Nqueen(n);
    cout <<"皇后最多种摆放个数" <<" "<<sum<< endl;
}

这里写图片描述

### N皇后问题回溯法算法实现与原理 #### 1. 回溯法的核心思想 回溯法是一种系统化的试探法,它通过逐步构建候选并不断评估其可行性来决问题。对于N皇后问题而言,目标是将N个皇后放置在一个N×N的棋盘上,使得它们互不攻击。这意味着任意两个皇后不能位于同一行、同一列或同一条对角线上。 为了满足这些约束条件,回溯法采用了一种深度优先搜索的方式,逐行尝试放置皇后,并利用剪枝技术排除不可能的情况。具体来说,当某个位置被选作皇后的放置点时,程序会检查这个位置是否违反了上述规则。如果发现冲突,则立即停止对该路径的进一步探索;如果没有冲突,则继续向下一层递归处理剩余未安排的位置[^1]。 #### 2. 算法的具体步骤 以下是基于C++语言的一种典型实现方式: ```cpp #include <iostream> using namespace std; class Queen { public: bool Place(int k); void BackTrack(int t); void Output(); int n; int* x; long sum; }; bool Queen::Place(int k) { for (int j = 1; j < k; j++) { if ((abs(k - j) == abs(x[j] - x[k])) || (x[k] == x[j])) return false; } return true; } void Queen::BackTrack(int t) { if (t > n) { Output(); sum++; } else { for (int i = 1; i <= n; i++) { x[t] = i; if (Place(t)) BackTrack(t + 1); } } } void Queen::Output() { for (int i = 1; i <= n; i++) cout << " (" << i << "," << x[i] << ")"; cout << endl; } ``` 在此代码片段中定义了一个名为`Queen`的类用于封装整个求过程中的状态变量以及主要操作函数。其中包含了三个重要成员函数: - `Place`: 负责检测当前位置是否合法; - `BackTrack`: 实现核心递归逻辑; - `Output`: 打印当前找到的一组有效布局方案[^4]。 #### 3. 时间复杂度分析 由于每次都需要考虑新的可能位置,并且要验证之前已放下的所有皇后之间的关系,因此理论上最坏情况下的时间开销接近O(N!)级别。然而实际运行过程中往往能够借助有效的剪枝手段大幅减少不必要的计算量,从而提高整体性能表现[^5]。 #### 4. 结果输出形式说明 最终结果通常以二维数组的形式呈现出来,每一个元素要么标记为'Q'(表示此处存在一个皇后),要么为空白字符'.',以此直观反映出各个皇后在整个棋盘上的确切分布状况[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值