【DFS】不撞南牆不回頭—深度優先搜尋演算法[Deep First Search]
阿新 • • 發佈:2018-11-09
今天上午聽到,那個非常6+1的李詠先生因癌症去世
DFS演算法的基本模型
深度下,不撞南牆不回頭,就是一直往後找,知道沒有路了,向後返回。
想起一首民謠,《可能否》--木小雅 https://music.163.com/#/song?id=569214126
現在可能也就民謠還有一些安靜了,好像雷子的歌也有點厭了。
木小雅Olivia:謝謝雲村pick我這塊小石頭,也謝謝優秀的製作團隊,更謝謝來聽這首歌的你。願多年以後,你撞過的南牆,都成為坦途;你遇見過的絕望,都成為最美的盛放。
今天也要上班嗎:不撞南牆不回頭 不見黃河不死心。
UP:山有木兮木有枝,心悅君兮君不知。
好了話歸正題。
void dfs(int step){
//1 判斷達到邊界了嗎
//2 沒有達到邊界就嘗試每一種方法
for(i=1;i<=n;i++){
//繼續下一步
dfs(step+1);
}
return;
}
兩個例題
1
#include <iostream> #include <stdio.h> #include <stdlib.h> using namespace std; int a[10],book[10],total=0; /*[][][]+[][][]==[][][] []種只能填1-9,每個數字只能使用一次 暴力列舉方法 和 DFS方法 還是9個格子,放九張牌 */ void dfs(int step){ int i; if(step == 10){//判斷邊界 就是所以格子都填滿了 滿足!? if((a[1]+a[4])*100+(a[2]+a[5])*10+a[3]+a[6] == a[7]*100+a[8]*10+a[9]){ total++; printf("%d%d%d+%d%d%d=%d%d%d\n", a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]); } return; } for(i=1;i<=9;i++){ if(book[i] == 0){ a[step]=i; book[i]=1; dfs(step+1); book[i]=0; } } return; } int main(){ dfs(1); printf("%d",total/2); system("pause"); return 0; }
2
#include <iostream> #include <stdio.h> #include <stdlib.h> using namespace std; int a[10],book[10],n;// a[]為盒子陣列 book[i]用來表示i有沒有用到,n為盒子數目 //全域性變數在沒有賦值以前系統預設為0,而區域性變數在沒有賦值以前的值是不確定的,所以在宣告區域性變數的時候一定要初始化。 /*本題是 啊哈演算法第四章 撲克牌的全排列 有N張不同的撲克牌 和 N個不同格子 最多有 N!個排列方式 對於第一個 格子有N種選擇,第二個 N—1個選擇,最後一個 1個 格子因為順序,相互獨立,相乘運算。 跟生物 N種氨基酸可組成N長的氨基酸鏈相同 */ /*0—>【1】 【2】 【3】,4{ 4 不存在} 假設有三張牌1,2,3,三個格子123 step—>一步一步向前放牌,到4的時候說明放好了一次例如 1 2 3輸出 收回【3】中的牌沒有其他方法, 再收回【2】中的,此時【2】處的for迴圈已經讀過2了,所以還有一種排序, 【2】處放入 3,dfs(step+1)->【3】處還可以放入2 這樣遞迴自己 收回【1】……………,遞迴給出答案 */ void dfs(int step){//深度優先搜尋演算法 Deep First Search int i; if(step == n+1){//step超出格子【N】範圍說明完成一次排序 for(i=1;i<=n;i++){ printf("%d",a[i]); } printf("\n"); return;//返回之前最近一次呼叫DFS的地方, } //處於Step位置,沒有達到要輸出就,判斷這個位置可以放入什麼牌 for(i=1;i<=n;i++){ if(book[i] == 0){//for迴圈判斷撲克牌 I是否還在手中 a[step]=i;//在放入格子 book[i]=1;//表明已經使用 dfs(step+1);//向下一格子看看,遞迴 book[i]=0;//完成一次就收回剛剛嘗試的撲克牌,進行下一次嘗試 } } return; } int main(){ scanf("%d",&n);//N個格子和撲克 dfs(1);//從第一次格子開始放 system("pause");//暫停 return 0; }