先上代碼,其中是用p[0]來存儲當前符合的次數,基本思路就是一行一行尋找合適的位子,若本行沒有則返回上一行,在上一行查找合適的位子。相對於用循環,遞歸的整體代碼思路更清晰。
//檢查當前行上的皇后位子是否合理,是返回true
bool Check(vector<int>&p,int line)
{
//當前行與前幾行的皇后位子進行規則比較,判斷當前行皇后位子是否合理
for(int i = 1;i < line;i++)
{
//在同一列或在對角線上,返回false
if(p.at(line) == p.at(i) || abs(p.at(i) - p.at(line)) == abs(i-line))
return false;
}
return true;
}
void QueesRun(vector<int>&p,int line,int length)
{
p.at(line) = 1;//每行皇后初始位子都是從第一個開始
for(int i=1;i<=length;i++)
{
if(Check(p,line))
{
if(line == length)//如果已經到最底行,並且每行都滿足,則加一
p.at(0) ++;
else//進行下一行皇后選位
QueesRun(p,line + 1,length);
}
if(p.at(line) == length)//當前行位子已經全部試過,則將上一行皇后位子進行重新尋找
return ;
p.at(line) ++;//當前行皇后的位子進行加
}
}
int main(int argc, char const *argv[])
{
vector<int> p;
p.resize(9,0); //9可以更改成其他數字N+1,就爲N皇后了
QueesRun(p,1,p.size() - 1);
cout << "總共有:" << p.at(0) << endl;
return 0;
}
運行結果
借用一下百度百科對八皇后問題的描述:https://baike.baidu.com/item/%E5%85%AB%E7%9A%87%E5%90%8E%E9%97%AE%E9%A2%98/11053477?fromtitle=%E5%85%AB%E7%9A%87%E5%90%8E&fromid=10742426&fr=aladdin
八皇后問題,是一個古老而著名的問題,是回溯算法的典型案例。該問題是國際西洋棋棋手馬克斯·貝瑟爾於1848年提出:在8×8格的國際象棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。 高斯認爲有76種方案。1854年在柏林的象棋雜誌上不同的作者發表了40種不同的解,後來有人用圖論的方法解出92種結果。計算機發明後,有多種計算機語言可以解決此問題。
思路:
1.首先考慮用什麼方法去完成,這裏是用一維數組加遞歸,原本是打算用循環的,寫着寫着發現那樣太囉嗦了,就換成遞歸了
2.位子的合理性判斷,即上面代碼Check()函數的實現,檢查當前行與之前行的皇后是否在攻擊範圍,不在,則返回true;
3.對每一行的皇后位子進行遍歷,尋找合適位子安放皇后,如果當前行的皇后安放位置滿足條件,則進入下一行。
4.當全部行都滿足的時候,p[0]++;然後return再次尋找合適位子。以此往復,便可以找出所有解了。