回溯法,又被稱為「試探法」。解決問題時,每進行一步,都是抱著試試看的態度,如果發現當前選擇並不是最好的,或者這麼走下去肯定達不到目標,立刻做回退操作重新選擇。這種走不通就回退再走的方法就是回溯法。
很多人認為回溯和遞迴是一樣的,其實不然。在回溯法中可以看到有遞迴的身影,但是兩者是有區別的。
回溯法從問題本身出發,尋找可能實現的所有情況。和窮舉法的思想相近,不同在於窮舉法是將所有的情況都列舉出來以後再一一篩選,而回溯法在列舉過程如果發現當前情況根本不可能存在,就停止後續的所有工作,返回上一步進行新的嘗試。
遞迴是從問題的結果出發,例如求 n!,要想知道 n!的結果,就需要知道 n*(n-1)! 的結果,而要想知道 (n-1)! 結果,就需要提前知道 (n-1)*(n-2)!。這樣不斷地向自己提問,不斷地呼叫自己的思想就是遞迴。
回溯和遞迴唯一的聯絡就是,回溯法可以用遞迴思想實現。
使用回溯法解決問題的過程,實際上是建立一棵「狀態樹」的過程。例如,在解決列舉集合所有子集的問題中,對於每個元素,都有兩種狀態,取還是舍,所以構建的狀態樹為:
圖1 狀態樹
回溯法的求解過程實質上是先序遍歷「狀態樹」的過程。樹中每乙個葉子結點,都有可能是問題的答案。圖 1 中的狀態樹是滿二叉樹,得到的葉子結點全部都是問題的解。
在某些情況下,回溯法解決問題的過程中建立的狀態樹並不都是滿二叉樹,因為在試探的過程中,有時會發現此種情況下,再往下進行沒有意義,所以會放棄這條死路,回溯到上一步。在樹中的體現,就是在樹的最後一層不是滿的,即不是滿二叉樹,需要自己判斷哪些葉子結點代表的是正確的結果。
八皇后問題是以西洋棋為背景的問題:有八個皇后(可以當成八個棋子),如何在 8*8 的棋盤中放置八個皇后,使得任意兩個皇后都不在同一條橫線、縱線或者斜線上。
圖 2 八皇后問題示例(#代表皇后)
八皇后問題是使用回溯法解決的典型案例。演算法的解決思路是:
從棋盤的第一行開始,從第乙個位置開始,依次判斷當前位置是否能夠放置皇后,判斷的依據為:同該行之前的所有行中皇后的所在位置進行比較,如果在同一列,或者在同一條斜線上(斜線有兩條,為正方形的兩個對角線),都不符合要求,繼續檢驗後序的位置。
如果該行所有位置都不符合要求,則回溯到前一行,改變皇后的位置,繼續試探。
如果試探到最後一行,所有皇后擺放完畢,則直接列印出 8*8 的棋盤。最後一定要記得將棋盤恢復原樣,避免影響下一次擺放。
源**:
#include int queenes[8]=,counts=0;
int check(int line,int list);
int count = 0;
//check函式,若通過檢查返回1,否則返回0
int check(int x, int y)
for (int i = 0; i < x; i++)
return 1;
}//goback,如果發現這一層任何位置都不可以放置皇后,則回退到上一層
void goback()
}//顯示8皇后位置
void showpos()
printf("\n");
} for (int i = 0; i < 8; i++)
printf("第%d個八皇后\n",countshow);
}int main()
count++;
} showpos();
system("pause");
return 0;
}
C語言回溯法解八皇后問題 八皇后演算法
在乙個西洋棋棋盤上放置八個皇后,使得任何兩個皇后之間不相互攻擊,求出所有的布棋方法,並推廣到n皇后情況。啥文字都不用看,b站上有個非常詳細的動畫 解說,上鏈結!click here include include include using namespace std void put queen ...
n皇后問題(C C語言實現)回溯法
按照西洋棋的規則,乙個皇后可以攻擊與之處在同一行或是同一列或同一條斜線上的其他任何棋子。則n皇后問題的要求為,在乙個n n的棋盤上放置n個皇后,使得任何兩個皇后不能被放在同一行或同一列或同一條斜線上。從空棋盤開始,設在第1行至第m行都已經正確地放置了m個皇后,再在第m 1行上找合適的位置放置第m 1...
八皇后問題(回溯法)
問題描述 八皇后問題是十九世紀著名數學家高斯於1850年提出的。問題是 在8 8的棋盤上擺放8個皇后,使其不能互相攻擊,即任意的兩個皇后不能處在同意行,同一列,或同意斜線上。可以把八皇后問題拓展為n皇后問題,即在n n的棋盤上擺放n個皇后,使其任意兩個皇后都不能處於同一行 同一列或同一斜線上。問題分...