日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

回溯法——N皇后问题

發布時間:2024/4/17 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 回溯法——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; }

運行結果:

下面呈遞非遞歸回溯代碼:

//N皇后問題 //非遞歸回溯 class Queen {int 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]))//觸發這兩個條件,皇后有碰撞返回false{return false;}}return true;}void Print(){for (int i = 1; i <= n; i++){for (int j = 1; j <= n; ++j){if (x[i] == j){printf("Q");}else{printf("#");}}printf("\n");}printf("\n");}int nQueen(){int t = 1;x[t] = 1;while ( x[1] <= n )//第一個皇后位置超了即結束{if (t > n)//t>n,說明最后一個皇后找到合適位置了{sum++;Print();t--;//回溯,調整前一個皇后的位置,找其他成功方案x[t]++;//如果x[t]超過n,會繼續回溯到上一個皇后}if (!Place(t) && x[t] <= n)//如果x[t]值不合適,且沒嘗試到最后,就讓第t個皇后向后放{x[t]++;}else if(x[t] <= n )//第t個皇后找到合適位置,放下一個皇后{t++;if (t <= n)//注意可能是最后一個皇后放成功了,t++就會大于n,所以放置越界,需要加if語句判斷{x[t] = 1;}}else//第t個皇后沒有找到適合的位置,回溯 {x[t] = 1;//注意先把該值置為1再回溯,因為下次放這個皇后肯定要從1繼續向后試探合適位置t--;//回溯到上一個皇后x[t]++;//如果皇后位置++后大于n,會繼續回溯到上一個皇后}}return sum;}};int main() {Queen qu(6);int sum = qu.nQueen();cout << sum << endl;return 0; }

這一次我們用6皇后作為測試用例,運行結果:

總結

以上是生活随笔為你收集整理的回溯法——N皇后问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。