文章目录
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;
}