演算法學習 DFS與BFS

2021-08-11 07:08:07 字數 3535 閱讀 6084

一。深度優先搜尋

深度優先搜尋

是一種列舉所有完整路徑以遍歷所有情況的搜尋方法。

類似樹的先根遍歷。簡單來說,就是一直往深處走,直到找到解或走不下去了為止。

可以使用棧來實現,用棧儲存未被檢測的結點,結點按照深度優先的次序被訪問並依次被壓入棧中,並以相反的次序出站進行新的檢測。

也可以使用遞迴實現,相對**簡潔,

但使用遞迴的時候系統會呼叫系統棧來存放遞迴中每一層的狀態,亦是用到了棧。

舉個栗子:

有n件物品,每件物品的重量為w[i],價值為c[i]。現在需要選出若干件物品放入乙個容量為v的揹包中,使得在選入揹包中的物品重量和不超過容量v的前提下,讓揹包中物品的價值之和最大,求最大價值。(1 <= n <= 20)

分析:

岔路口——每件物品選或不選兩種選擇

死胡同——選擇的物品重量總和不能超過v

**實現:

#include const int maxn = 30;

int n ,v, maxvalue = 0; //物品件數n,揹包容量v, 最大價值maxvalue

int w[maxn], c[maxn]; //w[i]為每件物品重量,c[i]為每件物品價值

void dfs(int index, int sumw, int sumc)

return;

} dfs(index+1, sumw, sumc); //不選第index件物品

dfs(index+1, sumw+w[index], sumc+c[index]); //選第index件物品

} int main()

dfs(index+1, sumw, sumc); //不選第index件物品

if(sumw + w[index] <= v)

dfs(index+1, sumw+w[index], sumc+c[index]); //選第index件物品

} }

再舉乙個栗子,理解一下dfs函式該怎麼寫:

給定n個整數(可能有負數),從中選擇k個數,使得這k個數之和恰好等於乙個給定的整數x:如果有多種方案的話,選擇他們中元素平方和最大的乙個。資料保證這樣的方案唯一。

int n, k, x, maxsumsqu = -1, a[maxn];  //序列a中n個數選k個數使其和為x,最大平方和為maxsumsqu

vectortemp, ans; //temp存放臨時方案,ans存放平方和最大的方案

// 當前處理index號整數,當前已選整數個數為nowk

// 當前已選整數之和為sum,當前已選整數平方和為sumsqu

void dfs(int index, int nowk, int sum, int sumsqu)

return;

} // 已經處理完n個數,或者超過k個數,或者和超過x,返回

if(index == n || nowk > k || sum > x) return;

// 選index號數

temp.push_back(a[index]);

dfs(index+1, nowk + 1, sum + a[index], sumsqu + a[index] * a[index]);

temp.pop_back();

// 不選index號數

dfs(index+1, nowk, sum, sumsqu);

}

二。廣度優先搜尋bfs一般用佇列儲存未被檢測的結點,且總是按照層次的順序進行遍歷。

類似樹的按層次遍歷的過程。

以上模板注釋:

(1)定義佇列q,並將起點s入隊

(2)寫乙個while迴圈,迴圈條件是佇列q非空

(3)在while迴圈中,先取出隊首元素top,然後訪問它(訪問可以是任何事情,例如將其輸出)。訪問完後將其出隊。

(4)將top的下一層結點中所有未曾入隊的結點入隊,並標記他們的層號為now的層號+1,同時設定這些入隊的結點已入過隊。

(5)返回(2)繼續迴圈

舉個栗子:

給出乙個m*m的矩陣,矩陣中的元素為0或1。我們稱位置(x, y)與其上下左右四個位置(x, y+1)、(x, y-1)、(x+1, y)、(x-1, y)是相鄰的。如果矩陣中有若干個1是相鄰的(不必兩兩相鄰),那麼我們稱這些1構成了乙個「塊」。求給定的矩陣中「塊」的個數。

例如上面的6*7的矩陣中,「塊」的個數為4。

思路:

列舉每乙個位置的元素,如果為0則跳過;如果為1,則使用bfs查詢與該位置相鄰的四個位置(前提是不出界),判斷他們是否為1(如果某個相鄰的位置為1,則同樣去查詢與該位置相鄰的四個位置,直到整個「1」塊訪問完畢)。

而防止走回頭路,一般可以設定乙個bool型陣列inq(即in queue的簡寫)來記錄每個位置是否在bfs中已入過隊。

乙個小技巧:對當前位置(x, y)來說,由於與其相鄰的四個位置分別為(x, y+1)、(x, y-1)、(x+1, y)、(x-1, y),那麼可以設定兩個增量陣列,來表示四個方向(0, 1)、(0, -1)、(1, 0)、(-1, 0)。

這樣我們可以使用for迴圈來列舉四個方向,以確定與當前座標(nowx, nowy)相鄰的四個位置,如下:

**實現:

#include #include using namespace std;

const int maxn = 100;

struct nodenode;

int n, m;

int matrix[maxn][maxn]; //01矩陣

bool inq[maxn][maxn] = ; //記錄位置(x, y)是否已入過隊

int x[4] = ;

int y[4] = ;

bool judge(int x, int y)

//bfs函式訪問位置(x,y)所在的塊,將該塊中所有"1"的inq都設定為true

void bfs(int x, int y)

} } }

int main(){

scanf("%d%d", &n, &m);

for(int x = 0; x

進一寸有一寸的歡喜。藉此學習下演算法。

算了算還有8天考ccf,考多少分無所謂啦。

BFS和DFS演算法學習總結

bfs 這是一種基於佇列這種資料結構的搜尋方式,它的特點是由每乙個狀態可以擴充套件出許多狀態,然後再以此擴充套件,直到找到目標狀態或者佇列中頭尾指標相遇,即佇列中所有狀態都已處理完畢。廣度優先搜尋 bfs 有乙個有向圖如圖a 圖a廣度優先搜尋的策略是 從起始點開始遍歷其鄰接的節點,由此向外不斷擴散。...

BFS與DFS演算法

dfs總結 首先,我們先了解一下bfs,bfs又稱廣度優先搜尋,一般都是用於解決一些圖,樹的遍歷問題。其實廣度優先搜尋就類似與二叉樹的層序遍歷過程,需要借助c 中stl裡面的queue佇列容器來實現這個過程。它其實就是一種分層查詢的過程,每次向前走一步,都會去訪問一批可以訪問的節點,不會存在dfs裡...

演算法 DFS與BFS

一 dfs 深度優先搜尋 dfs 深度優先遍歷dfs與樹的先序遍歷比較類似。假設初始狀態是圖中所有頂點均未被訪問,則從某個頂點v出發,首先訪問該頂點然後依次訪問它的所有鄰接結點,每次訪問乙個鄰接結點時,以該鄰接結點為根結點繼續進行dfs,直到結點的所有鄰接結點以及其鄰接結點的鄰接結點都被訪問完,才訪...