實際上回溯法有暴力破解的意思在里面,解決一個問題,一路走到底,路無法通,返回尋找另 一條路。
回溯法可以解決很多的問題,如:N皇后問題和迷宮問題。
一.概念
回溯算法實際類似枚舉的搜索嘗試過程,主要是在搜索嘗試過程中尋找問題的解,當發現不滿足條件的時候,就回溯返回,嘗試別的路徑。
百度解釋:回溯法(探索與回溯法)是一種選優搜索法,又稱為試探法,按選優條件向前搜索,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,而滿足回溯條件的某個狀態的點稱為“回溯點”。
二.基本思想
在包含問題的所有解的解空間樹中,按照深度優先搜索的策略,從根結點出發深度探索解空間樹。當探索到某一結點時,要先判斷該結點是否包含問題的解,如果包含,就從該結點出發繼續探索下去,如果該結點不包含問題的解,則逐層向其祖先結點回溯。(其實回溯法就是對隱式圖的深度優先搜索算法)。
若用回溯法求問題的所有解時,要回溯到根,且根結點的所有可行的子樹都要已被搜索遍才結束。
而若使用回溯法求任一個解時,只要搜索到問題的一個解就可以結束。
三.n皇后問題
////N皇后是典型DPS問題,這里是用遞歸實現的,要想輸出必須要存儲上級運算結果。 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<string> #include<cctype> #include<cmath> #include<map> #include<set> #include<vector> #include<queue> #include<stack> #include<ctime> #include<algorithm> #include<climits> using namespace std; const int N=101; static int disp[16]; int C[N]; int tot; int n; void search(int cur) { if(cur==n){ for( int i = 0; i<n; i++ ) printf( "%d " , disp[i] ); printf("\n"); tot++; } else for(int i=0;i<n;i++) { int ok=1; C[cur]=i;//嘗試把cur行的皇后放在第i列 for(int j=0;j<cur;j++)//檢查是否和前面的皇后沖突 if(C[cur]==C[j]||cur-C[cur]==j-C[j]||cur+C[cur]==j+C[j]) { ok=0;break; } if(ok) { disp[cur]=i;//當前行的皇后在第幾列 search(cur+1); } } } int main() { while(cin>>n) { tot=0; search(0); cout<<tot<<"種方法"<<endl; } return 0; }
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> using namespace std; int c[150],vis[3][150],tot,n=8,sum_max; int mapn[9][9]; void search(int cur) { if(cur==n)//遞歸邊界,只要走到了這里,所有皇后必然不沖突 { if(sum_max<tot) sum_max = tot; } else for(int i=0;i<n;i++) { if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n])//利用二維數組直接判斷 {//0為豎行,1為副對角線,2為主對角線 c[cur] = i;//保存下每行皇后的位置 tot += mapn[cur][i]; vis[0][i] = vis[1][cur+i] = vis[2][cur-i+n] = 1; search(cur+1); vis[0][i] = vis[1][cur+i] = vis[2][cur-i+n] = 0;//記得改回來 tot -= mapn[cur][i]; } } } int main() { int T; cin >> T; while(T--) { sum_max = 0,tot = 0; memset(vis,0,sizeof(vis)); for(int i=0;i<8;i++) for(int j=0;j<8;j++) { cin >> mapn[i][j]; } search(0); printf("%5d\n",sum_max); } return 0; }