深度優先搜索小結

深度優先搜索(DFS)

深度優先搜索就好比走迷宮, 不斷順着一條路走, 直到走不通爲止, 然後回退到上一個路口再向另外的方向行走(走過的方向就不會再走了,又不是傻子, 知道走不通,還向走不通的方向走), 不斷重複(試過所有路口, 狀態轉移), 重複直到找到唯一的一條合適的路徑;
DFS可以看做是二叉樹的先序遍歷, 多說無益; 直接上題;

例1:
給定a1, a2, a3,…an個數, 從中選出若干個數, 使他們的和恰好爲K
輸入: n=4; a={1,2,4,7}; K=13;
輸出: 2+4+7=13
分析: 當初我看到這道題, 就是懵逼狀態, 唉, DFS還沒搞清楚就開始做題, 很蠢, 不扯那些沒用的, 迴歸主題: 從給出的例子來看, 既然我們要從1,2,4,7中選出若干個數, 那就可以暴力枚舉, 循環列舉出a集合的冪集, 找出滿足條件的答案; 但是這種方法的複雜度讓我瘮得慌, 複雜度爲O(n^n), so, 這種做法就果斷放棄, 從今天的主題來看勢必要用到DFS來解決問題(我這不廢話嗎, 唉), 從DFS的定義來看就是狀態轉移, 這裏的狀態轉移表示的是每個數都擁有兩個選擇的權利, 要麼加, 要麼不加, 就好比走迷宮有兩條路, 要麼朝左, 要麼朝右, 你把這個過程想象走迷宮, 每種選擇都對應着不同的走法, 總有一條路是對的(看成一棵長得像二叉樹一樣的迷宮), 因此複雜度爲2的n次方, 相比前面的n的n次方下降了很多, 儘管下降了很多但是在實際應用需要做剪枝優化, 就題論事有如下代碼:

#include<iostream>
using namespace std;
int n=4,a[4]={1,2,4,7},k=13;
bool dfs(int i,int sum){
	if(i==n)return sum==k;//滿足條件然後進行迴歸
	if(dfs(i+1,sum)) {//在交叉口做選擇
//		cout<<" "<<a[i]<<endl;
//	如果沒加就不用輸出a[i],忽略了這個問題 
		return true;
	}
	if(dfs(i+1,sum+a[i])){
		cout<<" "<<a[i]<<endl;
		return true;
	}
	return false;
}
int main(){
	cout<<dfs(0,0)<<endl;
	return 0;
} 

上述整個過程可看做二叉樹的前序遍歷, 當滿足條件便迴歸
深度優化搜索總是從最開始的狀態出發,遍歷所有可能到達的狀態, 由此可對所有產生的狀態進行操作

例2:
在這裏插入圖片描述
這道題是深度優化搜索的一個很好例子, 拿來作爲參考
分析: 以第一個題作爲啓示, 第一個題可看做單連通域進行遍歷, 總共只在main函數中使用了一次dfs, 而這道題當遇到積水時就需要使用dfs, 一次dfs就能對相連的’w’進行遍歷,直到一個連通域遍歷完成, 如圖總共有3個連通域, 多說無益看代碼:

#include<iostream>
using namespace std;
int N=10,M=12;
char field[10][12]={
	"w.......ww.",
	".www....ww.",
	"...w.....w.",
	".........w.",
	".........w.",
	"wwww.....ww",
	"www.......w",
	"ww........w",
	"ww........w",
	"w.........."};
void dfs(int x,int y){
	field[x][y]='.';
	for(int dx=-1;dx<=1;dx++){
		for(int dy=-1;dy<=1;dy++){//針對當前'w'的8個方向使用dfs, 直到一個連通域遍歷完成
			int nx=x+dx,ny=y+dy;
			if(0<=nx&&nx<N&&0<=ny&&ny<M&&field[nx][ny]=='w')//滿足條件開始遍歷
				dfs(nx,ny);
		}
	}
	return;
} 
int main(){
	int res=0;
	for(int i=0;i<N;i++){
		for(int j=0;j<M;j++){
			if(field[i][j]=='w'){//針對整個地圖使用dfs
				dfs(i,j);
				++res;
			}
		}
	}
	cout<<res<<endl;
}

每個格子至多被調用一次, 所以複雜度O(N*M)
總的來說, 深度優化搜索就是對圖結構進行遍歷(以二叉樹的前序遍歷的方式), 直到遇到符合條件的情況

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章