一。深度優先搜尋
深度優先搜尋
是一種列舉所有完整路徑以遍歷所有情況的搜尋方法。
類似樹的先根遍歷。簡單來說,就是一直往深處走,直到找到解或走不下去了為止。
可以使用棧來實現,用棧儲存未被檢測的結點,結點按照深度優先的次序被訪問並依次被壓入棧中,並以相反的次序出站進行新的檢測。
也可以使用遞迴實現,相對**簡潔,
但使用遞迴的時候系統會呼叫系統棧來存放遞迴中每一層的狀態,亦是用到了棧。
舉個栗子:
有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,直到結點的所有鄰接結點以及其鄰接結點的鄰接結點都被訪問完,才訪...