DFS学习笔记

文章目录

  1. DFS是什么?
  2. DFS的实现方法(伪代码)
  3. DFS题目分类

1、DFS是什么?

就是选择一条路,如果无路可走,就打上标记,选择另外一条路(有选择性的暴力枚举,像树)。DFS基于递归思想,通过递归的形式来缩小问题规模,把一件事分割成若干个相同的小事,逐步完成。DFS需要一个标记数组,记录有没有被访问过。
DFS时间复杂度:O(n²)

如图:

在这里插入图片描述
借鉴百度


2、DFS的实现方法(伪代码)

代码如下:

void dfs () {
	if (符合题目要求) {
		... //按照题目要求
		return;
	}
	if (路径不合法) return;
	for (往下走) {
		if (题目有后效性) {//做题时别写这个!!!
			标记;
			dfs (往下扩展);
			取消标记;
		}
		else dfs (往下扩展);//也别写这个......
	}
	return;
}

3、DFS题目分类

(1)、走迷宫 (几种情况往下走)
例题:
农夫约翰的农场可以表示成N*M(1≤N≤1001≤M≤100)个方格组成的矩形。由于近日的降雨,在约翰农场上的不同地方形成了池塘。每一个方格或者有积水(‘W’)或者没有积水(’.’)。农夫约翰打算数出他的农场上共形成了多少池塘。一个池塘是一系列相连的有积水的方格,每一个方格周围的四个方格都被认为是与这个方格相连的。现给出约翰农场的图样,要求输出农场上的池塘数。
代码如下:

//思路:在每一个点搜索一遍,答案数+1,接着把能走过的路都走一遍(染色)
#include<bits/stdc++.h>
using namespace std;
int n , m , ans = 0 ;
int tx , ty ;
int dx [4] = {0 , -1 , 0 , 1};//定义四方向
int dy [4] = {-1 , 0 , 1 , 0};
char ch ;
int g[101][101];
void dfs (int x , int y){
	g[x][y] = 1 ;//打上标记
	for (int i = 0 ; i <= 3 ; i ++) {
    	tx = dx[i] + x;
    	ty = dy[i] + y;
    	if (tx <= n && tx > 0 && ty <= m && ty > 0 && g[tx][ty] == 0/*判断往下走合不合法*/) 
    		walk (tx , ty);
	}
	return ;
}
int main() {
	cin >> n >> m;
	for (int i = 1 ; i <= n ; i ++) {
		for (int j = 1 ; j <= m ; j ++) {
			cin >> ch;
			if (ch == '.') g[i][j] = 1 ;
			if (ch == 'W') g[i][j] = 0 ;//初始化
		}
	}
	for (int i = 1 ; i <= n ; i ++){
		for (int j = 1 ; j <= m ; j ++) {
			if (g[i][j] == 0) {
				ans ++ ;
				dfs(i , j) ;//在每一个点搜索一遍
			}
		}
	}
	cout << ans << endl;
	return 0;
}

(2)、选数形 (两种情况)
例题
已知 n 个整数 x1,x2,…,xn,以及一个整数 k(k<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22 3+7+19=29 7+12+19=38 3+12+19=34。
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29)。

代码如下:

//思路:通过一层层判断选或者不选的方式,确定选什么数,然后判断它是不是质数
#include<bits/stdc++.h>
using namespace std;
int x[10011];
int n , k , temp = 0;
int ans = 0;
bool is_prime (int n) {//判断是不是质数
	if (n < 2) return false;
	for (int i = 2 ; i <= sqrt (n) ; i ++ ) {
		if (n % i == 0) return false;
	}
	return true;
}
void dfs (int dep , int choose , int sum) {
	if (dep > n) {//如果超出层数
		if (choose == k) {//判断符不符合要求
			if (is_prime(sum)) {
				ans ++ ;
				return ;
			}
		}
	}
	else {
		dfs (dep + 1 , choose , sum);
		dfs (dep + 1 , choose + 1 , sum + x[dep]);//分两层往下走
	}
	return ;
}
int main () {	
	cin >> n >> k;
	for (int i = 1 ; i <= n ; i ++ ) cin >> x[i];
	dfs (1 , 0 , 0);
	cout << ans << endl;
	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值