国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

深度優(yōu)先搜索(DFS)(算法筆記)

這篇具有很好參考價值的文章主要介紹了深度優(yōu)先搜索(DFS)(算法筆記)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

本文內容基于《算法筆記》和官方配套練題網站“晴問算法”,是我作為小白的學習記錄,如有錯誤還請體諒,可以留下您的寶貴意見,不勝感激。


前言

深度優(yōu)先搜索是一種枚舉所有完整路徑以遍歷所有情況的搜索方法,總是以“深度”作為前進的關鍵詞。實現(xiàn)方式是有很多,最常見的是遞歸。


一、深度優(yōu)先搜索概述

深度優(yōu)先搜索屬于搜索問題的一種,當問題可以被描述為“路徑搜索”時,就可以采用搜素問題的所有解的方式來進行解決,所以DFS本質還是暴力。

深度搜索具有兩個關鍵詞,即“岔道口”和“死胡同”,這兩個詞來源于迷宮問題,這也是搜索問題最原始的表現(xiàn)。當碰到岔道口時,總是以“深度”作為前進的關鍵詞,不碰到死胡同就不回頭,因此被稱為“深搜”。深搜適合于求解需要遍歷所有解或路徑的問題,并且剪枝很重要。深搜和廣搜在數據結構中的應用就是對非線性存儲結構進行遍歷。

搜索和分治是兩大分析問題的方法,而回溯、剪枝、動態(tài)規(guī)劃可以說是對深度搜索和分治算法進行優(yōu)化。

二、算法設計

在使用遞歸進行DFS時,將遞歸式作為搜索中的“岔道口”,將遞歸邊界作為搜索中的“死胡同”,所以在設計DFS算法時,關鍵就是找準問題中的“岔道口”和“死胡同”。接下來通過實際例子介紹DFS,這里采用“晴問算法”中的題,書中的例題就不放了。

1.迷宮可行路徑數

深度優(yōu)先搜索,算法筆記,深度優(yōu)先,算法,圖論
這道題是接下來一系列問題的核心,下面的問題都是基于這道題進行局部修改。
首先分析“岔道口”:
每次移動可以選擇上下左右各一格進行移動,也就是說每次有四種選擇,即四個岔道口,設當前坐標為(x ,y),四個岔道口的選擇就分別為:(x+1,y),(x-1,y),(x,y+1),(x,y-1)。
其次分析“死胡同”:
當搜索到坐標位置元素為1時,表示無法通過,即無法繼續(xù)搜索,這時這條路徑便走到了盡頭;當搜索到終點時,就不用繼續(xù)搜索了。所以一共存在兩個遞歸邊界。
接下來就可以設計DFS()函數:
根據上面“岔道口”的設計,我們需要設置初始狀態(tài),即起點。用x表示行坐標,用y表示列坐標,所以函數看起來設這樣的:
void DFS(int x , int y , int n , int m){···},當然,n和m可以放在外面。
遞歸邊界:
if(number[x][y] == 1) return; //死胡同
if(x == n && y == m) { //走到終點
countr++; //計數器
return;
}
岔路口的選擇:
需要路徑在可移動范圍內移動:不允許到曾經到過的地方并且不能出界,所以設置散列表標記曾經走過的位置,注意起點的狀態(tài),不論哪條路起點肯定是必須走的。如果滿足移動條件,就沿岔路口移動。
完整代碼如下:

#include<cstdio>  //迷宮首先要確定起點和終點  
#include<algorithm>
#include<iostream> 
using namespace std;

const int MAXN = 5;
int number[MAXN][MAXN] = {};
int countr = 0;
bool hashTable[MAXN][MAXN] = {true}; //這就不是優(yōu)化了,如果不設這個條件,就會到達不了遞歸邊界 
//注意起點的狀態(tài),肯定要經過起點 
void DFS(int x , int y , int n , int m){
	if(number[x][y] == 1)  return;  //死胡同 
	if(x == n && y == m) {
		countr++;
		return;
	}     //核心:四個岔路口 
	if(x + 1 <= n && hashTable[x + 1][y] == false) { //短路與,順序也不能亂,不然會報錯 
		hashTable[x + 1][y] = true;  //注意一定是先把狀態(tài)更新,先選上,再走 
		DFS(x + 1 , y , n , m);
		hashTable[x + 1][y] = false; //恢復狀態(tài) 
	}
	if(x - 1 >= 0 && hashTable[x - 1][y] == false) {
		hashTable[x - 1][y] = true;
		DFS(x - 1 , y , n , m);
		hashTable[x - 1][y] = false;
	}
	if(y + 1 <= m && hashTable[x][y + 1] == false) {
		hashTable[x][y + 1] = true;
		DFS(x , y + 1 , n , m);
		hashTable[x][y + 1] = false;
	} 
	if(y - 1 >= 0 && hashTable[x][y - 1] == false) {
		hashTable[x][y - 1] = true;
		DFS(x , y - 1 , n , m);
		hashTable[x][y - 1] = false;
	}
}

int main(){
	int n , m;
	scanf("%d%d", &n , &m);
	for(int i = 0; i <= n - 1; i++)
		for(int j = 0; j <= m - 1; j++)
			scanf("%d", &number[i][j]);
	DFS(0 , 0 , n - 1, m - 1);
	printf("%d", countr);
}

2.指定步數的迷宮問題

深度優(yōu)先搜索,算法筆記,深度優(yōu)先,算法,圖論
這個問題在第一個問題的基礎上更改計數器就可以了,相當于新加了一個遞歸深度的計數器。需要注意的是當存在滿足K步的路徑時,就不需要繼續(xù)搜索了,這時直接用回溯算法進行優(yōu)化,返回上一層。
完整代碼如下:

#include<cstdio>  //迷宮首先要確定起點和終點  
#include<algorithm>
#include<iostream> 
using namespace std;

const int MAXN = 5;
int number[MAXN][MAXN] = {};
bool flag = false;
int k;
bool hashTable[MAXN][MAXN] = {true}; //這就不是優(yōu)化了,如果不設這個條件,就會到達不了遞歸邊界 
//注意起點的狀態(tài),肯定要經過起點 

void DFS(int x , int y , int n , int m , int countr){ //countr可以設成參數隨搜索動態(tài)變化,也可以像hashTable一樣恢復狀態(tài),就是一個記錄遞歸深度的計數器 
	if(flag) return;
	if(number[x][y] == 1) {  //死胡同
		return;   
	}
	if(x == n && y == m) {
		if(countr == k) flag = true;
		return;
	}     //四個岔路口 
	if(x + 1 <= n && hashTable[x + 1][y] == false) { //短路與,順序也不能亂,不然會報錯 
		hashTable[x + 1][y] = true;  //注意一定是先把狀態(tài)更新,先選上,再走 
		DFS(x + 1 , y , n , m , countr+1);
		hashTable[x + 1][y] = false; //恢復狀態(tài) 
	}
	if(x - 1 >= 0 && hashTable[x - 1][y] == false) {
		hashTable[x - 1][y] = true;
		DFS(x - 1 , y , n , m , countr+1);
		hashTable[x - 1][y] = false;
	}
	if(y + 1 <= m && hashTable[x][y + 1] == false) {
		hashTable[x][y + 1] = true;
		DFS(x , y + 1 , n , m , countr+1);
		hashTable[x][y + 1] = false;
	} 
	if(y - 1 >= 0 && hashTable[x][y - 1] == false) {
		hashTable[x][y - 1] = true;
		DFS(x , y - 1 , n , m , countr+1);
		hashTable[x][y - 1] = false;
	}
}

int main(){
	int n , m;
	scanf("%d%d%d", &n , &m , &k);
	for(int i = 0; i <= n - 1; i++)
		for(int j = 0; j <= m - 1; j++)
			scanf("%d", &number[i][j]);
	DFS(0 , 0 , n - 1, m - 1 , 0);
	if(flag == true) printf("Yes");
	else printf("No");
}

3.矩陣最大權值

深度優(yōu)先搜索,算法筆記,深度優(yōu)先,算法,圖論
這道題也是加一個計數器就可以了,不過記錄的是權值,即坐標位置元素的值。
完整代碼如下:

#include<cstdio>  //迷宮首先要確定起點和終點  
#include<algorithm>
#include<iostream> //權值隨著搜索而動態(tài)改變 
using namespace std;

const int MAXN = 5;
int number[MAXN][MAXN] = {};
int MAX = -10e6;
bool hashTable[MAXN][MAXN] = {true}; //這就不是優(yōu)化了,如果不設這個條件,就會到達不了遞歸邊界 
//注意起點的狀態(tài),肯定要經過起點 
void DFS(int x , int y , int n , int m , int value){
	if(x == n && y == m) {
		if(value > MAX) MAX = value;
		return;
	}     //核心:四個岔路口 
	if(x + 1 <= n && hashTable[x + 1][y] == false) { //短路與,順序也不能亂,不然會報錯 
		hashTable[x + 1][y] = true;  //注意一定是先把狀態(tài)更新,先選上,再走 
		DFS(x + 1 , y , n , m , value + number[x + 1][y]);
		hashTable[x + 1][y] = false; //恢復狀態(tài) 
	}
	if(x - 1 >= 0 && hashTable[x - 1][y] == false) {
		hashTable[x - 1][y] = true;
		DFS(x - 1 , y , n , m , value + number[x - 1][y]);
		hashTable[x - 1][y] = false;
	}
	if(y + 1 <= m && hashTable[x][y + 1] == false) {
		hashTable[x][y + 1] = true;
		DFS(x , y + 1 , n , m , value + number[x][y + 1]);
		hashTable[x][y + 1] = false;
	} 
	if(y - 1 >= 0 && hashTable[x][y - 1] == false) {
		hashTable[x][y - 1] = true;
		DFS(x , y - 1 , n , m , value + number[x][y - 1]);
		hashTable[x][y - 1] = false;
	}
}

int main(){
	int n , m;
	scanf("%d%d", &n , &m);
	for(int i = 0; i <= n - 1; i++)
		for(int j = 0; j <= m - 1; j++)
			scanf("%d", &number[i][j]);
	DFS(0 , 0 , n - 1, m - 1 , number[0][0]);
	printf("%d", MAX);
}

4.矩陣最大權值路徑

深度優(yōu)先搜索,算法筆記,深度優(yōu)先,算法,圖論
這道題可以開數組記錄走過的坐標,并設置最大權值之和路徑數組,如果權值之和更大,交換數組。注意更新數組狀態(tài),不要影響其他路徑的選擇。
完整代碼如下:

#include<cstdio>  //迷宮首先要確定起點和終點  
#include<algorithm>
#include<iostream> //權值隨著搜索而動態(tài)改變 
#include<vector>//這里也不知道開多長,就用vector實現(xiàn)吧 , 這道題是前面的整合,走一步記一下,如果權值更大,更新結果數組 
using namespace std;
const int MAXN = 5;
int number[MAXN][MAXN] = {};
int MAX = -10e6;
vector <int> temp , ans;
bool hashTable[MAXN][MAXN] = {true}; //這就不是優(yōu)化了,如果不設這個條件,就會到達不了遞歸邊界  
//注意起點的狀態(tài),肯定要經過起點 
void DFS(int x , int y , int n , int m , int value){
	if(x == n && y == m) {
		if(value > MAX) {
			MAX = value;
			ans = temp;
		}
		return;
	}     //核心:四個岔路口 
	if(x + 1 <= n && hashTable[x + 1][y] == false) { //短路與,順序也不能亂,不然會報錯 
		hashTable[x + 1][y] = true;  //注意一定是先把狀態(tài)更新,先選上,再走 
		temp.push_back(x + 1); 
		temp.push_back(y); 
		DFS(x + 1 , y , n , m , value + number[x + 1][y]);
		hashTable[x + 1][y] = false; //恢復狀態(tài) 
		temp.pop_back();
		temp.pop_back();
	}
	if(x - 1 >= 0 && hashTable[x - 1][y] == false) {
		hashTable[x - 1][y] = true;
		temp.push_back(x - 1) ; 
		temp.push_back(y);
		DFS(x - 1 , y , n , m , value + number[x - 1][y]);
		hashTable[x - 1][y] = false;
		temp.pop_back();
		temp.pop_back();
	}
	if(y + 1 <= m && hashTable[x][y + 1] == false) {
		hashTable[x][y + 1] = true;
		temp.push_back(x) ; 
		temp.push_back(y + 1);
		DFS(x , y + 1 , n , m , value + number[x][y + 1]);
		hashTable[x][y + 1] = false;
		temp.pop_back();
		temp.pop_back();
	} 
	if(y - 1 >= 0 && hashTable[x][y - 1] == false) {
		hashTable[x][y - 1] = true;
		temp.push_back(x) ; 
		temp.push_back(y - 1);
		DFS(x , y - 1 , n , m , value + number[x][y - 1]);
		hashTable[x][y - 1] = false;
		temp.pop_back();
		temp.pop_back();
	}
}

int main(){
	int n , m;
	scanf("%d%d", &n , &m);
	for(int i = 0; i <= n - 1; i++)
		for(int j = 0; j <= m - 1; j++)
			scanf("%d", &number[i][j]);
	temp.push_back(0);temp.push_back(0);  
	DFS(0 , 0 , n - 1, m - 1 , number[0][0]);
	for(vector<int> :: iterator it = ans.begin(); it != ans.end(); it = it + 2){  //迭代器遍歷
		printf("%d %d\n", *it + 1 , *(it + 1) + 1);
	}
		
}

三、備注

1.遞歸只是一種實現(xiàn)方法,分治法和搜索都可以采用遞歸實現(xiàn),且相對其他方法更簡單,只是運行效率低且容易爆站,所以需要算法優(yōu)化;
2.分治法和搜索雖然實現(xiàn)方式都是遞歸,但在分析問題時是兩種不同的是思想;
3.回溯優(yōu)化是指當遞歸滿足某些條件時就可以停止遞歸返回上一層,所以回溯的前提是必須存在可行解保證可以走到遞歸邊界,否則會死遞歸;
4.剪枝優(yōu)化是指在面對岔路口時,在滿足某些條件時,可以減少岔路口的選擇;
5.注意優(yōu)化和遞歸邊界的區(qū)別,遞歸邊界是問題必須滿足的最后條件,而優(yōu)化是在題目條件的限制上來減少計算量;
6.搜索算法并不只存在于數據結構的圖論中,雖然最初接觸DFS和BFS時是在數據結構中,但實際這是一種算法,當問題滿足可以搜索的性質時,就可以運用搜索算法;
7.注意遞歸中參數的作用域;
8.全排列適合用分治解決,組合適合用搜索解決;文章來源地址http://www.zghlxwxcb.cn/news/detail-718338.html

到了這里,關于深度優(yōu)先搜索(DFS)(算法筆記)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 【算法詳解 | DFS算法】深度優(yōu)先搜索解走迷宮問題 | 深度優(yōu)先圖遍歷

    【算法詳解 | DFS算法】深度優(yōu)先搜索解走迷宮問題 | 深度優(yōu)先圖遍歷

    by.Qin3Yu 本文需要讀者掌握 結構體 和 棧 的操作基礎,完整代碼將在文章末尾展示。 特別聲明:本文為了盡可能使用簡單描述,以求簡單明了,可能部分專有名詞定義不準確。 棧相關操作可以參考我的往期博文: 【C++數據結構 | 棧速通】使用棧完成十進制數轉二四八進制數

    2024年02月03日
    瀏覽(19)
  • 第一周算法訓練(dfs)(深度優(yōu)先搜索算法)

    第一周算法訓練(dfs)(深度優(yōu)先搜索算法)

    dfs: 深度優(yōu)先搜索算法 ,是一種用于遍歷或 搜索樹或圖的算法 .沿著樹的深度遍歷樹的節(jié)點,盡可能深的搜索樹的分支。當節(jié)點v的所在邊都己被探尋過,搜索將回溯到發(fā)現(xiàn)節(jié)點v的那條邊的起始節(jié)點。這一過程一直進行到已發(fā)現(xiàn)從源節(jié)點可達的所有節(jié)點為止。如果還存在未被

    2024年02月20日
    瀏覽(20)
  • Python 算法基礎篇:深度優(yōu)先搜索( DFS )和廣度優(yōu)先搜索( BFS )

    Python 算法基礎篇:深度優(yōu)先搜索( DFS )和廣度優(yōu)先搜索( BFS )

    深度優(yōu)先搜索( DFS )和廣度優(yōu)先搜索( BFS )是兩種常用的圖遍歷算法,用于在圖中搜索目標節(jié)點或遍歷圖的所有節(jié)點。本篇博客將介紹 DFS 和 BFS 算法的基本概念,并通過實例代碼演示它們的應用。 ???? ?? ?? ?? 深度優(yōu)先搜索( DFS )是一種用于遍歷或搜索圖或樹

    2024年02月07日
    瀏覽(53)
  • 深度優(yōu)先搜索(DFS)和廣度優(yōu)先搜索(BFS)兩種算法c++

    深度優(yōu)先搜索(DFS)和廣度優(yōu)先搜索(BFS)兩種算法c++

    深度優(yōu)先搜索(DFS)和廣度優(yōu)先搜索(BFS)是一種用于遍歷或搜索樹圖的一種算法,在這個過程中保證圖或數的每個結點被訪問且僅被訪問一次,再按照每個結點訪問的順序不同分為深搜和廣搜。 本文只討論這兩種算法在搜索方面的應用! 深度優(yōu)先搜索 ( Depth-First-Search,DFS )它 沿

    2024年02月13日
    瀏覽(20)
  • 圖的遍歷(搜索)算法(深度優(yōu)先算法DFS和廣度優(yōu)先算法BFS)

    圖的遍歷(搜索)算法(深度優(yōu)先算法DFS和廣度優(yōu)先算法BFS)

    從圖的某個頂點出發(fā)訪問遍圖中所有頂點,且每個頂點僅被訪問一次。(連通圖與非連通圖) 1、訪問指定的起始頂點; 2、若當前訪問的頂點的鄰接頂點有未被訪問的,則任選一個訪問之;反之,退回到最近訪問過的頂點;直到與起始頂點相通的全部頂點都訪問完畢; 3、若

    2024年01月17日
    瀏覽(26)
  • 【數據結構與算法】搜索算法(深度優(yōu)先搜索 DFS和廣度優(yōu)先搜索 BFS)以及典型算法例題

    【數據結構與算法】搜索算法(深度優(yōu)先搜索 DFS和廣度優(yōu)先搜索 BFS)以及典型算法例題

    【數據結構與算法】系列文章鏈接: 【數據結構與算法】遞推法和遞歸法解題(遞歸遞推算法典型例題) 【數據結構與算法】系列文章鏈接: 【數據結構與算法】C++的STL模板(迭代器iterator、容器vector、隊列queue、集合set、映射map)以及算法例題 【數據結構與算法】系列文章鏈

    2024年04月13日
    瀏覽(30)
  • 如何實現(xiàn)一個簡單的深度優(yōu)先搜索(DFS)算法?

    如何實現(xiàn)一個簡單的深度優(yōu)先搜索(DFS)算法?

    前端入門之旅:探索Web開發(fā)的奇妙世界 記得點擊上方或者右側鏈接訂閱本專欄哦 幾何帶你啟航前端之旅 歡迎來到前端入門之旅!這個專欄是為那些對Web開發(fā)感興趣、剛剛踏入前端領域的朋友們量身打造的。無論你是完全的新手還是有一些基礎的開發(fā)者,這里都將為你提供一

    2024年02月07日
    瀏覽(21)
  • 【Python搜索算法】深度優(yōu)先搜索(DFS)算法原理詳解與應用,示例+代碼

    【Python搜索算法】深度優(yōu)先搜索(DFS)算法原理詳解與應用,示例+代碼

    目錄 1 基本原理 2 DFS算法流程 3 時間復雜度 4 空間復雜度 5 DFS算法應用案例: 5.1 解決路徑查找問題? 5.2 解決圖的連通性問題 5.3? 拓撲排序 5.4? 在樹結構中進行深度遍歷 深度優(yōu)先搜索(DFS)是一種重要的圖遍歷算法,用于探索圖中的節(jié)點和邊。 DFS 是一種遞歸或棧(堆棧)

    2024年02月06日
    瀏覽(45)
  • 【圖論算法】深度優(yōu)先搜索的應用

    【圖論算法】深度優(yōu)先搜索的應用

    深度優(yōu)先搜索 (depth-first search)是對先序遍歷(preorder traversal)的推廣。我們從某個頂點 v 開始處理 v,然后遞歸地遍歷所有鄰接到 v 的頂點。 對一棵樹的所有頂點的訪問需 O(|E|) 時間。對任意圖進行該過程時則需要考慮避免圈的出現(xiàn)。為此,當訪問一個頂點 v 的時候,由于當時已

    2024年02月08日
    瀏覽(90)
  • DFS(深度優(yōu)先搜索算法)入門保姆級超詳解

    DFS(深度優(yōu)先搜索算法)入門保姆級超詳解

    如題,本篇創(chuàng)作目的在于更精細化理解DFS的運作,篇幅不長,也只是作者的一家之言,只為提供一個對入門者的更精細的解釋。 DFS,深度優(yōu)先搜索算法,首先我們看中文,可以很清楚的理解到這個算法是指搜索操作中優(yōu)先進行深度也就是縱向的數據篩查。 看搜索的基本思路

    2024年02月07日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包