基础算法系列之深度优先搜索

Posted 一米阳光213

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基础算法系列之深度优先搜索相关的知识,希望对你有一定的参考价值。

      在计算机的基础算法领域,深度优先搜索无疑是非常重要的一种编程方法,它的作用和价值,类似于常规算法中的排序,具有两个特点:

    (1)常用。当我们需要搜索问题的解决方案时,最常用的只有两种方法:深度优先搜索和广度优先搜索;

    (2)标准化。与快速排序类似,虽然实现的方法千变万化,但是遵循固定的步骤,第一步做什么,第二步做什么,都非常的明确。所以呢,只要吃透几个经典的问题,有了深刻的体会之后,所有这类问题都很 easy 了。

       这篇文章的使命:由浅入深,讲透深度优先搜索算法。所以,这篇文章我会认真对待,持续地修改,最后的目的是:

    (1)从入门到熟练:在本文的基础部分,即使是不了解深度优先搜索算法的童鞋,也能够准确、快速和熟练地掌握深度优先搜索;

    (2)从熟练到精通:在本文的进阶部分,即使是熟悉深度优先搜索算法的童鞋,也能够进一步加深加强对深度优先搜索的理解和掌握。

      为了不断提高本文的质量和水平,同时也因为我自己水平有限,所以希望各位提出宝贵意见 ~

    例题 POJ 2251 综合了3D深度优先和3D广度优先搜索

    题目传送门:http://poj.org/problem?id=2251

// 非常经典的深度优先搜索和广度优先搜索
//
#include<iostream>
#include<vector>
#include<queue>
#include<string.h>
using namespace std;
/*********** 全局变量 ******************/
int L, R, C;
char G[31][31][31];
int ans = 0;         // 走出迷宫的最少步数
int start_row, start_col, start_level;
int exit_row, exit_col, exit_level;
int min(int a, int b)
	return a > b ? b : a;


// 如果被访问过,则标记为'T'
void dfs(int level, int row, int col, int steps)
	// Step 1: Termination condition
	if (level == exit_level && row == exit_row && col == exit_col)
		ans = min(ans, steps);
		return;
	

	// Step 2: 确定搜索范围
	int dl[6] =  1, -1, 0, 0, 0, 0 ;
	int dr[6] =  0, 0, 1, -1, 0, 0 ;
	int dc[6] =  0, 0, 0, 0, 1, -1 ;
	for (int i = 0; i < 6; i++)
		int new_level = level + dl[i];
		int new_row   = row + dr[i];
		int new_col   = col + dc[i];
		// Step 3: 排除无效的搜索
		if (new_level < 0 || new_level >= L || new_row < 0 || new_row >= R || new_col < 0 || new_col >= C || G[new_level][new_row][new_col] == '#' || G[new_level][new_row][new_col] == 'T')
			continue;
		// Step 4: 使用当前结点
		G[new_level][new_row][new_col] = 'T';
		// Step 5: 访问下一步的结点
		dfs(new_level, new_row, new_col, steps + 1);
		// Step 6: 弃用当前结点,换用下一个
		G[new_level][new_row][new_col] = '.';
	


/*************** BFS ****************/
struct node
	int level;
	int row;
	int col;
	int steps; // 已经走了多少步
	node(int l, int r, int c,int s)
		level = l;
		row = r;
		col = c;
		steps = s;
	
	node()
		level = row = col = 0;
	
;
int bfs()
	// Step 1: 放入第一个结点并标记
	node start(start_level, start_row, start_col,0);
	G[start_level][start_row][start_col] = 'T';
	queue<node> Q;
	Q.push(start);

	// Step 2: 开始主循环
	while (!Q.empty())
		// Step 3: 取出队列中第一个元素,并判断是否满足终止条件
		node cur = Q.front();
		Q.pop();
		if (cur.level == exit_level && cur.row == exit_row && cur.col == exit_col)
			return cur.steps;
		
		// Step 4: 访问下一步的结点
		int dl[6] =  1, -1, 0, 0, 0, 0 ;
		int dr[6] =  0, 0, 1, -1, 0, 0 ;
		int dc[6] =  0, 0, 0, 0, 1, -1 ;
		for (int i = 0; i < 6; i++)
			int new_level = cur.level + dl[i];
			int new_row = cur.row + dr[i];
			int new_col = cur.col + dc[i];
			// Step 5: 排除无效的搜索
			if (new_level < 0 || new_level >= L || new_row < 0 || new_row >= R || new_col < 0 || new_col >= C || G[new_level][new_row][new_col] == '#' || G[new_level][new_row][new_col] == 'T')
				continue;
			// Step 6: 使用当前结点
			G[new_level][new_row][new_col] = 'T';
			Q.push(node(new_level, new_row, new_col, cur.steps + 1));
		
	

	return -1; // 无法找到出口


int main(int argc, char * argv[])

	while (scanf("%d%d%d", &L, &R, &C) && L != 0)
		// Initialization
		memset(G, 0, sizeof(G));

		ans = 99999999;
		/*************** Input /***************/
		for (int l = 0; l < L; l++)
			for (int r = 0; r < R; r++)
			
				cin >> (G[l][r]);
				// 找到起始点和终止点
				for (int c = 0; c < C;c++)
				if (G[l][r][c] == 'S')
					start_level = l;
					start_row = r;
					start_col = c;
				
				else if (G[l][r][c] == 'E')
					exit_level = l;
					exit_row = r;
					exit_col = c;
				
			
			//char tmp[30];
			//cin.getline(tmp,30);
		
		
		/*************** Process /***************/
		int ans = bfs();

		/*************** Output /***************/
		if (ans == -1)
			cout << "Trapped!" << endl;
		else
			cout << "Escaped in " << ans << " minute(s)." << endl;
	
	return 0;

  

    例题1:POJ 1011 Sticks. 题目链接:题目描述

    无比经典的一道题目。可以说是必须弄懂的一道题目了。

    思路分析:

    (1)为什么要用深度优先搜索而不是广度优先搜索呢?

             解释:如果大家学过二叉树的深度优先遍历和广度优先遍历就知道,不管是深度优先还是广度优先,都是对整个解空间进行搜索,其结果是一样的,但是呢,广度优先搜索必须借助一种数据结构--队列,如果数据的规模较大,那么它必须消耗大量的内存。在本题中,最多有 64 根小木棍,假设最多需要 8 根小木棍,那么队列中的元素数量为:64 * 63 * 62 * ... * 57 = 1784629 亿,假设一个元素为 int 占 4 个字节,那么内存消耗将是 712 TB !  显然,广度优先行不通。

    (2)有哪些剪枝方法?

             一. 既然题目中没有指定这些小木棍的顺序,那么我们不妨对这些小木棍排序。升序 or 降序?取决于哪一种顺序有助于压缩搜索空间(即减少搜索次数)。假设小木棍长度分别为 1,2,3,4,5(升序排列),初始长度 init_len = 5,那么我们选中 1 之后,第二根选2,第三根选3,4,5都会导致失败,那么就会回溯到第二步,.... 省略后续。假设是降序排列,5,4,3,2,1,那么第一步选5,直接就凑好了一根原始木棍!第二步选4,再选1,又是一根!从这个例子可以看出,升序排列有助于压缩搜索空间,所以我们在输入所有小木棍长度之后,首先对其从大到小排序。

          二. 假设,第1-3根小木棍长度都为x,如果第1根凑失败了,后面的第2-3根小木棍也一定失败,不需要再搜索一次,换句话说,如果某一根长度为 x 的小木棍导致了失败,则跳过后面的相同长度的小木棍。

          三. 由基本常识可知,设初始木棍的长度为 init_len,所有小木棍的长度之和为 sum_len, 最长的小木棍长度为 max_len,则:init_len >= max_len,且 init_len 必定整除 sum_len。

        基于以上分析,用 C++ 代码实现如下:

// poj 1011 Sticks 深度优先搜索.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
/******************* 全局变量定义区 ***********************/
int a[66], n;	 // 小木棍的数量,以及每一根小木棍的长度
bool visit[66];	 // 因为是多个阶段的搜索(凑齐一根初始木棍可以看作是一个阶段),所以需要记忆哪些小木棍已经被使用了,下次搜索直接跳过这些已经被使用的小木棍 
int max_len = 0;
int sum_len = 0;

// 为了从大到小排序,必须定义这个函数
bool cmp(int a, int b)
	return a > b;


bool dfs(int num_finished_sticks, int init_len, int cur_len, int start_index)
	// Step 1: 确定我们 dfs 递归函数的终止条件
	if (num_finished_sticks == sum_len / init_len)	// 成功凑齐所有的初始木棍
		return true;

	// Step 2: 确定搜索范围: 从 (start_index) 到 (最后一根) 小木棍,都是可以进行搜索的。
	int cur_stick_length = -1;    // 例如,第1-3根小木棍长度都为x,如果第一根凑失败了,后面的第2-3根小木棍也一定失败,不需要再搜索一次
	for (int i = start_index; i < n; i++)
		// 剪枝: 剔除以下情况的新木棍
		// 第一种情况:已经使用过了。
		// 第二种情况:目前已经凑好的木棍长度 + 新木棍长度 > 初始木棍长度
		// 第三种情况:新木棍长度 = 已经证明失败的木棍的长度
		if ( visit[i] || cur_len + a[i] > init_len || a[i] == cur_stick_length ) continue;

		// Step 3: 访问当前的搜索结点
		visit[i] = true;

		// Step 4: 确定下一步的搜索策略
		if (cur_len + a[i] == init_len)   // 恰好凑出一根初始木棍
			if ( dfs(num_finished_sticks + 1, init_len, 0, 0))     // 请注意:搜索新一根初始木棍时,从头开始搜
				return true;
			else
				cur_stick_length = a[i];
		
		else // cur_len + a[i] < init_len
			if (dfs(num_finished_sticks, init_len, cur_len + a[i], i + 1)) // 请注意:搜索下一根小木棍时,不是从头开始搜,而是直接从下一根开始搜。为什么?请看下面的分析
				return true;
			else
				cur_stick_length = a[i];
		

		// Step 4: 处理失败的情况
		visit[i] = false;
		if (cur_len == 0)    // 剪枝:如果新棍子的第一根凑失败了,那么直接可以判定,整个凑棍过程一定失败。
			return false;
	

	return false;


int main(int argc, char * argv[])

	while (scanf("%d", &n) && n != 0)
		for (int i = 0; i < n; i++)
			scanf("%d", &a[i]);

		/**************** 剪枝:由于我们的 dfs 总是从第一根小木棍开始搜索,所以降序排列可以有效地压缩搜索空间  *****************/
		sort(a, a + n, cmp);


		/**************** 剪枝:由基本常识可知,初始木棍长度 >= 最长的小木棍 And 初始木棍长度一定能整除(所有小木棍的总长度) And 初始木棍至少有两根(至少本题的数据是这样的)  *****************/
		max_len = 0;    // 所有小木棍中,最长的小木棍的长度
		sum_len = 0;    // 所有小木棍的总长度
		for (int i = 0; i < n; i++)
		
			if (a[i] >= max_len)
				max_len = a[i];
			sum_len += a[i];
		
		bool found = false;
		for (int init_len = max_len; init_len <= sum_len / 2; init_len++)
			if (sum_len % init_len != 0) continue;    // 剔除不符合条件的初始木棍长度
			memset(visit, 0, sizeof(visit));

			if (dfs(0, init_len, 0, 0))							      // 成功地找到了初始木棍长度
				cout << init_len << endl;
				found = true;
				break;
			
		
		if (found == false)
			cout << sum_len << endl;
	

	return 0;


 

例题:牛客网 --> 好未来笔试题 --> 求和          题目链接:牛客网-好未来笔试题-求和

题目解读:从 1,2,...n 中,找若干个数使得它们和为 m ,打印出所有的组合。

分析: 基本的思路是,对 所有可能的组合 进行深度优先搜索遍历,一旦当前的方案恰好和为 m,打印之,并停止继续往更深的层次进行搜索。

思考:为什么这道题要用深度优先搜索而不是广度优先搜索?其实这题 dfs 和 bfs 都能解决问题,只是 dfs 在编写代码的时候很方便,容易写。

#include<iostream>
#include<stack>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
/*********** 题目描述:
输入两个整数 n 和 m,从数列1,2,3.......n 中随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来

************/
/******************** 分析思路: 采用深度优先搜索,一旦搜索到满足条件的组合,就输出 ********************/



int n, m, *a;
vector<int> st; // 存储当前搜索方案的数字栈
// next_index: the next index to search the array
// cur_sum: 当前已经凑好的数值
//  为了剪纸,压缩搜索空间,设置 failure 表示当前搜索是否成功
bool failure = false;


void dfs_search(int start_position, int cur_sum)
	// Step 1: Termination conditions
	if ( start_position >=n )  因为已经升序排列了,所以后面的肯定不会满足要求,直接PASS,剪枝
		return;
	

	// Step 2: 确定下一步的搜索方案
	for (int i = start_position; i < n; i++)
		// 是否使用当前方案
		if (cur_sum + a[i] > m) // 注意,回溯一步
			break;
		
		// 两种可能,一种是满足了目标要求,另一种是没有
		else if (cur_sum + a[i] == m)    // 满足了目标要求
			st.push_back(a[i]);
			// 输出当前的方案
			for (int j = 0; j < (int)st.size(); j++)
			if (j != st.size() - 1)
				printf("%d ", st[j]);
			else
				printf("%d\\n", st[j]);
			// 达到目标了,不要再继续往后面搜索。
			//break;
		
		else if(cur_sum + a[i] < m)						 // 
			st.push_back(a[i]);
			dfs_search(i + 1, cur_sum+a[i]);
			//st.erase(st.end() - 1);
			//cur_sum -= a[i];
		
		// Step 3: 处理失败的情况: 替换当前这个搜索结点
		if (st.empty()==false)
			st.erase(st.end() - 1);
	



int main(int argc, char * argv[])

	// Input
	cin >> n >> m;
	a = new int[n]; //memset(a, 0, sizeof(int)*n);
	for (int i = 0; i < n; i++)
		a[i] = i + 1;

	// Process
	// 1. Sort
	sort(a, a + n);
	// 2. DFS
	dfs_search(0, 0);

	return 0;

例题:POJ 3984 迷宫问题 题目链接:POJ 3984 迷宫问题

这道题的难点在于需要打印整个搜索的路径。深度优先搜索 or 广度优先搜索都是OK的。 因为广度优先搜索天然适合于求解最短路径问题,所以 bfs 比 dfs 在编写代码上更容易一些。

#include<iostream>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
/* 因为要打印最短路径,所以这个问题用广度优先搜索妥妥的
*  该问题的难点:需要记忆搜索的路径。怎么存储?什么数据结构?
*  可能的解决方案: 链表,一条路径就是一条链子。每一个结点只需要记住自己的父亲结点是谁,就足够我们进行回溯了!
*/
/***************** 全局变量定义区 ********************/
int G[5][5];
struct node
	node(int a, int b)
		x = a;
		y = b;
		prev = NULL;
	
	node(int a, int b, struct node * c)
		x = a;
		y = b;
		prev = c;
	
	node()
		x = 0;
		y = 0;
		prev = NULL;
	
	int x, y;			// 当前位置的坐标
	int steps;			// 当前走了多少步
	struct node * prev;	// 记录前一步的位置
;
typedef node * pnode;
struct link_node

;

/***************** 广度优先搜索 ********************/
void bfs()
	queue<pnode> Q;
	// Step 1: 初始化
	pnode cur = new node(0, 0, NULL);
	Q.push( cur );
	bool visit[5][5] =  false ;
	visit[0][0] = true;

	// Step 2: 进入主循环
	while (!Q.empty())
	
		// Step 3: 取出队列首部的元素
		pnode cur = Q.front(); Q.pop();
		// 判断是否达到结束条件
		if (cur->x == 4 && cur->y == 4)
			// 打印路径: 不断地进行回溯,直到空为止
			stack<node> trace;
			while (!(cur==NULL))
				trace.push( node(cur->x,cur->y) );
				cur = cur->prev;    
			
			//trace.push(node(0, 0));
			while (!trace.empty())
				node tmp = trace.top();
				trace.pop();
				printf("(%d, %d)\\n", tmp.y, tmp.x);
			
			break;  // 成功完成任务,直接强制退出
		
		// Step 4: 确定下一步的搜索策略
		int next_x, next_y;
		// left
		next_x = cur->x - 1;
		next_y = cur->y;
		if (next_x >= 0 && visit[next_y][next_x] == false && G[next_y][next_x] == 0)
			visit[next_y][next_x] = true;
			Q.push(new node(next_x, next_y,cur));
		
		// right
		next_x = cur->x + 1;
		next_y = cur->y;
		if (next_x <5 && visit[next_y][next_x] == false && G[next_y][next_x] == 0)
			visit[next_y][next_x] = true;
			Q.push(new node(next_x, next_y, cur));
		
		// up
		next_x = cur->x;
		next_y = cur->y-1;
		if (next_y>=0 && visit[next_y][next_x] == false && G[next_y][next_x] == 0)
			visit[next_y][next_x] = true;
			Q.push(new node(next_x, next_y, cur));
		
		// down
		next_x = cur->x;
		next_y = cur->y+1;
		if (next_y<5 && visit[next_y][next_x] == false && G[next_y][next_x] == 0)
			visit[next_y][next_x] = true;
			Q.push(new node(next_x, next_y, cur));
		
	


/***************** 深度优先搜索 ********************/
struct solution
	solution(int step, vector<node> t)
		steps = step;
		trace = t;
	
	int steps;			// 从左上角一直走到右下角的步数
	vector<node> trace; // 从左上角一直走到右下角的所有步骤,都存储于 trace 中
;
bool visited[5][5] =  false ;
vector<node> record;
vector<solution> solutions;
void dfs(int row, int col)
	// Step 1: Termination conditions
	if (row == 4 && col == 4)
		// 此时,这个方案不一定是最好的
		solutions.push_back(solution(record.size(), record));
		return;
	
	// Step 2: 确定搜索范围: 上,下,左,右
	int delta_x[4] =  0,  0, -1, 1 ;
	int delta_y[4] =  -1, 1, 0,  0 ;
	for (int i = 0; i < 4; i++)
		int next_x = col + delta_x[i]; 
		int next_y = row + delta_y[i];
		// Step 3: Visit the node !
		if (next_x <0 || next_x >4 || next_y<0 || next_y>4  || visited[next_y][next_x]|| G[next_y][next_x] != 0)
			continue;
		// 标记之
		visited[next_y][next_x] = true;
		// 存储之
		record.push_back(node(next_x, next_y));
		// Step 3: 确定下一步的搜索策略
		dfs(next_y, next_x);
		// Step 4: 处理失败策略
		// 反标记之
		visited[next_y][next_x] = false;
		// 反存储之
		record.pop_back();
		
	


int main(int argc, char * argv[])

	// Input
	for (int i = 0; i < 5;i++)
	for (int j = 0; j < 5; j++)
		scanf("%d", &G[i][j]);

	// Process
	//bfs();
	visited[0][0] = true;
	record.push_back(node(0, 0));
	dfs(0, 0);

	// find the shortest path
	int min_len = 99999;
	int min_index = -1;
	for (int i = 0; i < solutions.size(); i++)
		if (solutions[i].steps < min_len)
			min_len = solutions[i].steps;
			min_index = i;
		
	

	// Output
	for (int i = 0; i < solutions[min_index].steps; i++)
		printf("(%d, %d)\\n", solutions[min_index].trace[i].y, solutions[min_index].trace[i].x);
	

	return 0;


例题:POJ 1088 滑雪 深度优先搜索    题目链接:POJ 1088 滑雪 最大滑雪长度

#include<iostream>
using namespace std;
// 一个基本的先验知识是:设 G[x][y] 表示 (x,y) 位置的高度,设 dp[x][y]表示以(x,y)为起始点,所能滑雪的最大长度,那么 dp[x][y] = max( dp[x-1][y], dp[x+1][y], dp[x][y-1], dp[x][y+1] ) + 1,其中,G[x-1][y], G[x+1][y], G[x][y-1], G[x][y+1] 都小于 G[x][y]
//
/***************** 全局变量定义区 ********************/
int H, W, G[102][102];
bool visit[102][102];
int ans = 0;			// 最长的滑雪长度


/*************** 这道题也可以用动态规划的思路 ******************/
int max(int a, int b)
	return a > b ? a : b;

int dp[102][102]; // 重点:dp[x][y]表示以(x,y)为起始点,所能滑雪的最大长度
// POJ 运行时间:32 ms
int dfs_max_len(int x, int y)
	// Step 1: Termination conditions
	if (x < 0 || x >= W || y < 0 || y >= H )
		return 0;
	// Step 2: Visit the node
	visit[y][x] = true;
	// Step 3: Go deeper
	int max_len = 1;
	// left
	if (x - 1 >= 0 && G[y][x - 1] < G[y][x])
		max_len = max(max_len, dp[x-1][y] ==1 ? 1+ dfs_max_len(x - 1, y) : 1+ dp[x-1][y] );
	// right
	if (x + 1 <W && G[y][x + 1] < G[y][x])
		max_len = max(max_len,  dp[x+1][y]==1 ? 1+ dfs_max_len(x + 1, y) : 1+ dp[x+1][y]);
	// up
	if (y - 1 >= 0 && G[y-1][x] < G[y][x])
		max_len = max(max_len, dp[x][y-1]==1 ? 1+ dfs_max_len(x, y-1):1+ dp[x][y-1] );
	// down
	if (y + 1 < H && G[y + 1][x] < G[y][x])
		max_len = max(max_len, dp[x][y+1]==1 ? 1+ dfs_max_len(x, y + 1):1+ dp[x][y+1] );
	
	return max_len;


// POJ运行时间: 47 ms
int dfs_max_len_brute_force(int x, int y)
	// Step 1: Termination conditions
	if (x < 0 || x >= W || y < 0 || y >= H)
		return 0;
	// Step 2: Visit the node
	visit[y][x] = true;
	// Step 3: Go deeper
	int max_len = 1;
	// left
	if (x - 1 >= 0 && G[y][x - 1] < G[y][x])
		max_len = max(max_len,  1 + dfs_max_len(x - 1, y) );
	// right
	if (x + 1 <W && G[y][x + 1] < G[y][x])
		max_len = max(max_len,  1 + dfs_max_len(x + 1, y));
	// up
	if (y - 1 >= 0 && G[y - 1][x] < G[y][x])
		max_len = max(max_len,  1 + dfs_max_len(x, y - 1));
	// down
	if (y + 1 < H && G[y + 1][x] < G[y][x])
		max_len = max(max_len, 1 + dfs_max_len(x, y + 1));

	return max_len;



int DP()

	int ans = 0;	// 最长的滑雪长度
	for (int y = 0; y < H;y++)
	for (int x = 0; x < W; x++)
		// 记忆这个结果
		dp[x][y] = dfs_max_len_brute_force(x,y);
		ans = max(ans, dp[x][y]);
	
	return ans;


int main(int argc, char ** argv[])

	// Input
	cin >> H >> W;
	for (int i = 0; i < H;i++)
	for (int j = 0; j < W; j++)
	
		scanf("%d", &G[i][j]);
		// 初始化 dp 数组
		dp[j][i] = 1;
	
	// Process
	int ans = DP();

	// Output
	cout << ans << endl;

	return 0;

例题:POJ 2386 数数地图上有多少个水坑      题目链接:POJ 2386 地图上有多少个水坑

非常简单的深搜问题了,每搜到一个位置,就标记一下。

// 内存空间消耗量:732 K
// 运行时间: 63 ms

#include<iostream>
using namespace std;
/************** 全局变量定义 *****************/
int n, m; // 本题中地图有 n 行 m 列
char G[102][102];

/******* 基于深度优先搜索的“填水坑”函数
* 这道题目非常简单,不需要记忆任何的状态,也没有其他的限制条件
*/
void dfs_fill_pond(int row, int col)
	// Step 1 : Termination conditions
	if (row < 0 || row >= n || col < 0 || col >= m)
		return;
	if (G[row][col] == '.')
		return;
	// Step 2: 确定搜索范围:相邻的8个位置
	G[row][col] = '.';
	dfs_fill_pond(row - 1, col - 1);
	dfs_fill_pond(row - 1, col );
	dfs_fill_pond(row - 1, col + 1);
	dfs_fill_pond(row , col - 1);
	dfs_fill_pond(row , col + 1);
	dfs_fill_pond(row + 1, col - 1);
	dfs_fill_pond(row + 1, col );
	dfs_fill_pond(row + 1, col + 1);


int main(int argc, char * argv[])

	// Input
	cin >> n >> m;
	for (int row = 0; row < n;row++)
	for (int col = 0; col < m; col++)
		cin >> G[row][col];

	// Process
	int num_ponds = 0;
	for (int row = 0; row < n;row++)
	for (int col = 0; col < m; col++)
		if (G[row][col] == 'W')
			num_ponds++;
			dfs_fill_pond(row, col);
		

	

	// Output
	cout << num_ponds << endl;

	return 0;


未完待续。持续改进中......

以上是关于基础算法系列之深度优先搜索的主要内容,如果未能解决你的问题,请参考以下文章

算法系列之广度优先搜索与深度优先搜索

算法之深度优先搜索

算法之广度优先搜索

Python算法系列—深度优先遍历算法

图论深度优先搜索

算法之深度和广度优先搜索算法