N 皇后問題-回溯法

N 皇后問題:在 N × N  的棋盤上放置彼此不受攻擊的 N 個皇后,任意兩個皇后不同行、不同列、不同斜線。

思路

1. 因爲皇后不能同行,所以,在每一行放置一個皇后就行

2. 當在一行放置皇后的時候:

     1) 順序檢查這一行每一個位置是否和上面所有的皇后,只要有一個同列或者在斜線上就不能放置;若找到一個滿足的,放置在這個位置,開始下一行的皇后放置。

     2) 當此行所有位置都不滿足時,回溯到上一行,讓上一個行的皇后繼續選擇下一個合適的位置。

如此,直到所有行上都放上滿足條件的皇后,即爲一個解。


過程如下圖所示:



C++ 代碼

#include <iostream>
#include <cmath>
#include <cstdlib>

using namespace std;

class Queen {
private:
    int n;
    int* x;
    int sum;
public:
    Queen(int n) {
        this->n = n;
        sum = 0;
        x = new int[n+1];
        for(int i=0; i <= n; i++)
            x[i]=0;
    }

    int getSum() {
        return sum;
    }

    void Backtrack(int t) {
        if (t > n) {
            for(int i=1; i <= n; i++) {
                for(int j=1; j <= n; j++)
                    if(j == x[i])
                        cout << "Q" << " ";
                    else
                        cout << "#" << " ";
                cout << endl;
            }
            cout << endl;
            sum++;
        } else
            for (int i=1; i <= n; i++) {
                x[t] = i;
                //cout << "i:" << i << " " << "x[t]:" << x[t] << " " << "t:" << t << endl;
                if(constraint(t))
                    Backtrack(t+1);
            }
    }

    bool constraint(int k) {// 約束條件
        for (int i=1; i < k; i++)
            if((abs(k-i)==abs(x[i]-x[k]))||(x[i]==x[k]))
                return false;
        return true;
    }

    ~Queen() {
        delete[] x;
    }
};

int main() {
    cout << "           ------N皇后問題------" << endl;
    cout << "之回溯法求解\n" << endl;
    cout << "請輸入皇后的個數:";
    int n;
    cin >> n;
    Queen queen(n);
    cout << "\n" << n << "皇后問題的解爲:" << endl;
    queen.Backtrack(1);
    cout << "\n總共有" << queen.getSum() << "個解" << endl;
    system("PAUSE");
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章