八皇后問題不同思路解答

八皇后問題不同思路解答:

算法提出:

​在國際象棋棋盤上(8*8)放置八個皇后,使得任意兩個皇后之間不能在同一行,同一列,也不能位於同於對角線上。問共有多少種不同的方法,並且指出各種不同的放法。

思路一:回溯法

/*
算法提出:
    在國際象棋棋盤上(8*8)放置八個皇后,使得任意兩個皇后之間不能在同一行,同一列,也不能位於同於對角線上。問共有多少種不同的方法,並且指出各種不同的放法。
算法思路:
  首先我們分析一下問題的解,我們每取出一個皇后,放入一行,共有八種不同的放法,然後再放第二個皇后,同樣如果不考慮規則,還是有八种放法。於是我們可以用一個八叉樹來描述這個過程。從根節點開始,樹每增加一層,便是多放一個皇后,直到第8層(根節點爲0層),最後得到一個完全八叉樹。  
  緊接着我們開始用深度優先遍歷這個八叉樹,在遍歷的過程中,進行相應的條件的判斷。以便去掉不合規則的子樹。
  那麼具體用什麼條件來進行子樹的裁剪呢?
  我們先對問題解的結構做一個約定。
  用X[i]來表示,在第i行,皇后放在了X[i]這個位置。
  於是我們考慮第一個條件,不能再同一行,同一列於是我們得到x[i]不能相同。剩下一個條件是不能位於對角線上,這個條件不是很明顯,我們經過分析得到,設兩個不同的皇后分別在j,k行上,x[j],x[k]分別表示在j,k行的那一列上。那麼不在同一對角線的條件可以寫爲abs((j-k))!=abs(x[j]-x[k]),其中abs爲求絕對值的函數。
  於是下面我們便可以利用一個遞歸的調用來遍歷八叉樹。
*/

#include <iostream>
#include <cmath>

using namespace std;

static int num; //皇后數目
static int *x;  //存放皇后位置的數組
static int sum; //方案數目

//判斷位置是否符合條件
bool place(int k)
{
    for(int j = 1;j<k;j++)
        if(abs(x[k] - x[j]) == abs(k-j) || x[j] == x[k])
            return false;
    return true;

}

//訪問某節點所有子節點
void backtrack(int t)
{
    if(t>num) //num爲皇后的數目
    {
        sum++;//sum爲所有的可行的解
        for(int m = 1;m<num;m++)
        {
            cout<<x[m]<<" ";//這一行用輸出當遞歸到葉節點的時候,一個可行解
        }
        cout<<endl;
    }
    else
        for(int i = 1;i<=num;i++)
        {
            x[t] = i;
            if(place(t)) backtrack(t+1);//此處的place函數用來進行我們上面所說的條件的判斷,如果成立,進入下一級遞歸
        }
}

int main()
{
    num = 8;
    sum = 0;
    x = new int[num+1];
    for(int i= 0;i<=num;i++)
        x[i] = 0;

    backtrack(1);

    cout<<"方案共有"<<sum<<endl;

    return 0;

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