深度優先搜尋的學習
阿新 • • 發佈:2019-01-26
解決深度優先搜尋關鍵在於“當下該如何做”到”下一步該如何做“。
通常是把每一種方法都嘗試一遍,當這一步解決後進行下一步。
基本模型:
void dfs(int step)
{
判斷邊界
嘗試每一種可萌
for(int i=1;i<=n;i++){
繼續下一步
}
返回
}
舉例:
輸入一個數n,輸出1~n的全排列
/*全排列問題,舉個例子就是有幾張牌放在幾個不同盒子裡,有多少種情況*/ #include<iostream> using namespace std; int a[10], book[10], n;//a是牌,book是盒子,當book為1時說明有牌 void dfs(int step) { if (step == n + 1) {//當在第n+1和盒子時說明已經排完 for (int i = 1; i <= n; i++) { cout << a[i];//輸出牌 } cout << endl; return;//返回上一次呼叫時的dfs函式 } for (int i = 1; i <= n; i++) { if (book[i] == 0) {//判斷是否可以放牌 a[step] = i; book[i] = 1;//標記 dfs(step + 1);//遞迴,進行下一個盒子 book[i] = 0;//每次放完牌記得要清零 } } return; } int main() { cout << "輸入盒子個數" << endl; cin >> n; dfs(1);//從第一個盒子開始 return 0; }
再舉個例子:
有數字1~9,使得???+???+???=???成立
/*與盒子裡放牌是一個道理*/ #include<iostream> using namespace std; int a[10], book[10], total = 0;//total是有幾種可能 void dfs(int step) { if (step == 10) { if (a[1] * 100 + a[2] * 10 + a[3] + a[4] * 100 + a[5] * 10 + a[6] == a[7] * 100 + a[8] * 10 + a[9]) { total++; cout << a[1] << a[2] << a[3] << "+" << a[4] << a[5] << a[6] << "=" << a[7] << a[8] << a[9] << endl; } return; } for (int i = 1; i < 10; i++) { if (book[i] == 0) { a[step] = i; book[i] = 1; dfs(step + 1); book[i] = 0; } } return; } int main() { dfs(1); cout << "一共有" << total << "種可能" << endl; return 0; }
利用深度優先搜尋走迷宮
/*利用深度優先搜尋走迷宮, 輸入迷宮時0代表可以走,1代表不能走, 求最短路徑*/ #include<iostream> using namespace std; int a[51][51];//迷宮 int book[51][51];//用來儲存走過的點 int min = 999999;//步數的最小值 int p, q,m,n; void dfs(int x, int y, int step) { int next[4][2] = {//行走的座標 {0,1},//向右 {1,0},//向下 {0,-1},//向左 {-1,0}//向右 }; int next_x, next_y;//下一步的座標 if (x == p&&y == q) {//判斷是否完成 if (step < min) min = step;//儲存最小步數 return;//注意要返回上一次 } for (int i = 0; i < 4; i++) {//四種走法 next_x = x + next[i][0]; next_y = y + next[i][1]; if (next_x < 1 || next_x>n || next_y < 1 || next_y>m)//判斷越界 continue; if (a[next_x][next_y] == 0 && book[next_x][next_y] == 0) {//判斷是否能走 book[next_x][next_y] = 1;//標記走過的點 dfs(next_x, next_y, step + 1);//遞迴,進行下一步 book[next_x][next_y] = 0;//清零 } } return; } int main() { int start_x, start_y; cout << "輸入行和列" << endl; cin >> n >> m; cout << "輸入迷宮" << endl; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) cin >> a[i][j]; } cout << "輸入起始座標X" << endl; cin >> start_x; cout << "輸入起始座標Y" << endl; cin >> start_y; cout << "輸入終點座標X" << endl; cin >> p; cout << "輸入終點座標Y" << endl; cin >> q; book[start_x][start_y] = 1;//要把起點標記上,防止走重 dfs(start_x, start_y, 0);//起始步數為零 cout << min<<endl; return 0; }
如輸入:
5 4
0 0 1 0
0 0 0 0
0 0 1 0
0 1 0 0
0 0 0 1
1 1 4 3
結果為 7