我們依舊舉例說明,比如我們現在想要在a,b,c三個箱子中放入1,2,3三張牌,想知道乙個有多少種情況
首先我們一步步嘗試每一次,每乙個箱子中的放牌情況
我們約定,對於每個箱子,我們都優先放入1,然後是2,最後是3
當然,如果手上一張牌都沒有,也就說明某種情況被列舉完了
我們用乙個陣列a代表箱子,step代表第step個箱子,而i代表牌
我們利用下面這個迴圈來進行舉窮
for(i = 1;i<=n:i++ )
另外,一張牌只能用一次,因此我們還要加入乙個標記陣列book
我們約定: book[i]= 0 代表牌還在手上,=1代表用掉了
所以,我們能把**更新為:
for(i = 1;i<=n:i++ )
}
我們觀察整體的解法已經上述的舉窮,不難發現:我們想要的搜尋,實質上就是不斷使用上面的方法
所以,我們處理每個盒子的方法都是一樣的,我們之間把上述**變成方法
void dfs(int step)
}return ;
}
我們不斷按順序處理下去,每次都在方法中呼叫方法自身並把引數加一,我們把這樣的做法叫遞迴
另外,每乙個箱子嘗試之後,記得收回牌
事實上,開始「收牌」就意味著某一次的情況已經被舉完了
void dfs(int step)
}return ;
}
那麼我們的搜尋什麼時候是個頭呢,也就是我們搜到第n+1個盒子的時候
(因為卡牌數量和盒子是對應的,迴圈中n代表有幾張牌)
所以,處理到第n+1個盒子時,我們就列印出放法,然後return
p.s 不return就死迴圈了完整的方法**如下:
void dfs(int step)
//step是箱子處理第step個箱子
for(i = 1;i<=n:i++ )
}return ;
}
#incluide int a[10],book[10],n ;
void dfs(int step)
//step是箱子處理第step個箱子
for(i = 1;i<=n:i++ )
}return ;
}int main()
理解深度優先搜尋的關鍵在於解決當下該如何做以及下一步如何做的內容
而「下一步如何做」往往可以利用迴圈或遞迴解決
我們可以把深度優先演算法的模型概括為:
void dfs(int step)
返回 }
我們嘗試把深度優先演算法應用到迷宮求解路徑中去
實質上,很多搜尋演算法都是為這種事情服務的。
另外在尋路方面還有一位大佬,那就是a*,這是後話了
我們假設迷宮由n行m列的格仔組成,每個格仔要麼是空地要麼是障礙物
設我們的終點在(p,q),而起點在(1,1),尋找兩點之間的最短路徑
(設n,m均小於50)
首先明確人和計算機是不一樣,我們最重要的就是找乙個通用的搜尋法,然後一直用它直到結束
我們需要約定乙個順序進行搜尋,並且它是可以運用於每乙個格仔的
我們不妨這麼幹:
1.按照右,下,左,上的順序進行嘗試
2.檢測:障礙物無法到達,不可越界,不要去走過的點
3.下一點
另外,在每次行動的開始,我們還要判斷一件事,那就是是否到達了終點
終點檢測
那麼這麼乙個函式只需要三個引數: x,y,總步數
void dfs(int x, int y, int step)
}
順時針嘗試
我們利用乙個陣列來進行「嘗試」的描述
int next[4][2] = , //向右
, //向下
, //向左
//向上},
為什麼這麼設計呢,我們不妨把這個陣列想象為乙個向量
對於我們的地圖(它實質也是乙個二維陣列)而言,下標的增加代表向右/向下,減少則是向左/向上
因此在之後的計算中,利用next陣列可以迅速得到下乙個點的座標
我們再加上乙個for迴圈來列舉所有可能,就可以得到乙個嘗試的列舉
for(k=0;k<=3;k++)
這一部分要是覺得太抽象了,可以畫一下next陣列的樣子來理解,有空的話這裡會補圖
檢測:哪些地方不能去
主要進行下面三個判斷:
1.是否越界。根據tx,ty的數值以及地圖大小判斷即可
2.是否為障礙物。設定乙個陣列a來登記障礙物
3.是否已經走過。設定乙個標記陣列book進行標記
可能有人會提出:把走過的路加到障礙物陣列中就行了,這種想法很好但實際上卻是不方便的
book陣列的意義有兩個,一是標記走過的路,二是配合嘗試計算多個路徑(模擬一下之前的拿牌和收回牌)
這部分的判斷如下:
if(tx<1 || tx>n || ty<1 || ty>m )
if(a[tx][ty]==0 && book[tx][ty]==0)
#includeint n,m,p,q,min = 9999999 ;
int a[51][51] , book[51][51] ;
void dfs(int x, int y ,int step), //向右
, //向下
, //向左
//向上
};int tx,ty,k ;
//判斷是否到達目標點
if(x==p && y==q)
//列舉走法
for(k=0;k<=3;k++)
if(a[tx][ty]==0 && book[tx][ty]==0)
}return ;
}//主函式
int main()
}//讀入起點和終點
scanf("%d %d %d %d",&startx,&starty,&p,&q);
//開始設定
book[startx][starty] = 1;
//開始搜尋
dfs(startx,starty,0) ;
//輸出最短步數
printf("%d" , min);
getchar();getchar();
return 0 ;
}
深度優先搜尋DFS
作為搜尋演算法的一種,dfs對於尋找乙個解的 np 包括npc 問題作用很大。但是,搜尋演算法畢竟是 時間複雜度是o n 的階乘級演算法,它的效率比較低,在資料規模變大時,這種演算法就顯得力不從心了。關於深度優先搜尋的效率問題,有多種解決方法。最具有通用性的是剪枝 prunning 也就是去除沒有用...
深度優先搜尋 DFS
深度優先搜尋 縮寫dfs 有點類似廣度優先搜尋,也是對乙個連通圖進行遍歷的演算法。它的思想是從乙個頂點v 0開始,沿著一條路一直走到底,如果發現不能到達目標解,那就返回到上乙個節點,然後從另一條路開始走到底,這種盡量往深處走的概念即是深度優先的概念。你可以跳過第二節先看第三節,還是引用上篇文章的樣例...
深度優先搜尋(dfs)
深度優先搜尋的一般步驟 1 從頂點v出發,訪問v。2 找出剛才訪問過的頂點的第乙個未被訪問的鄰接點,訪問該頂點。以該頂點為新頂點,重複此步驟,直到剛訪問的頂點沒有沒有未被訪問過的鄰接點為止。3 返回前乙個訪問過的仍有未被訪問過的鄰接點的頂點,找出該頂點的下乙個未被訪問過的鄰接點,訪問該頂點。4 重複...