回溯法——N皇后问题
生活随笔
收集整理的這篇文章主要介紹了
回溯法——N皇后问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
N皇后問題即給一個n*n方格,將n個皇后放進去,要求皇后不能出現在同一列,同一行,也不能出現在對角線上,換句話說,只有折線才可能連接兩個皇后。我們拿四皇后來舉例:
如圖1,第三行的皇后放第一個各格子的話,和第一行的皇后處于同一列,所以不可以;放在第二個格子或者第四個的話,和第二行的皇后處于同一個對角線,所以不可以 ;放在第三個格子的話,和第二行的皇后處于同一列 ,所以不可以。
圖2和圖3是正確的放法。
在這里用一維數組就可以表示 皇后位置,比如n皇后,我們申請一個n+1空間大小的數組(申請n+1空間大小是為了下標和皇后好對應,0下標我們不用),下標對應的是第幾行的皇后,對應的值是皇后放在這一行的第幾個格子。
分析:
怎么表示兩個皇后的位置是合理的呢?
(1)不在同一列:即數組里的值都各不相等
(2)不在對角線上:abs(x[i]-x[j]) != abs(i-j)
只要滿足這兩個條件就合理,不滿足就不合理 。
注意:每次放完皇后,都要將這個皇后和前面所有的皇后判斷是否觸發這兩個條件。
先呈遞遞歸代碼:
// 遞歸 //一維數組,下標代表行,值代表列 class Queen {int n;//n皇后int* x;//數組int sum;//放法種數 public:Queen(int sz) :n(sz), sum(0){x = new int[n + 1];memset(x, 0, sizeof(int)*(n+1));//多申請了一個空間,0下標不放東西}~Queen(){delete[] x;x = NULL;}bool Place(int k)//k為下標,剪枝函數,返回真就說明皇后沒有碰撞,否則返回假{for (int i = 1; i < k; i++){if (x[i] == x[k] || abs(i - k) == abs(x[i] - x[k]))//判斷放的皇后位置是否合理{return false;}}return true;}void Print(){for (int i = 1; i <= n; i++){for (int j = 1; j <= n; ++j){if (x[i] == j)//打印皇后,用“Q”代表{printf("Q");}else//不是皇后的格子,用“#”代表{printf("#");}}printf("\n");}printf("\n");}void BackTrack(int t){if (t > n)//如果t>n就說明第n個皇后放置好了{sum += 1;Print();//打印 ,然后退回到上一個皇后放置問題,尋找其他正確路徑}else{for (int i = 1; i <= n; i++){x[t] = i;if (Place(t))//如果第t個皇后放置合理 ,就放置下一個,不合理就第t個皇后的位置向后面格子放,如果所有位置都不合理,會退回到上一層函數,即上一個皇后位置放置問題,對上一個皇后位置向后移,...遞歸{BackTrack(t + 1);}}}}int nQueen(){BackTrack(1);return sum;} };int main() {Queen qu(4);int sum = qu.nQueen();cout << sum << endl;return 0; }運行結果:
下面呈遞非遞歸回溯代碼:
這一次我們用6皇后作為測試用例,運行結果:
總結
以上是生活随笔為你收集整理的回溯法——N皇后问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 回溯法——打印子集树
- 下一篇: 回溯法——旅行售货员问题