1. 程式人生 > >【DFS】不撞南牆不回頭—深度優先搜尋演算法[Deep First Search]

【DFS】不撞南牆不回頭—深度優先搜尋演算法[Deep First Search]

今天上午聽到,那個非常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;
}