DFS入门

最近有一场机试,已经说了重点考察dfs,但是对dfs还不是很熟,所以借由学习dfs来输出笔记,从而加深印象。

一.概念

dfs,深度搜索算法,又可以认为是回溯算法,它其实就是一个决策树的遍历问题,遍历出所有情况,但是先深度后广度。用另外一个名称说这个问题其实就是穷举,穷举能做出的所有选择。

那么其实就是去思考三个问题:

  1. 当前做的选择
  2. 手上可以做的选择
  3. 什么时候不能做选择了?就是达到最后一个叶子结点的时候

最经典的问题当属全排列问题,如何排列出1-n所有数字,按字典顺序。拿acwing y神的一张图就是这样子写草稿:

那么我们可以看出要分别去做不同的选择最终得到所有结果,光讲可能抽象了点,我们看道题目

排列数字

给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法。

现在,请你按照字典序将所有的排列方法输出。

输入格式

共一行,包含一个整数 n。

输出格式

按字典序输出所有排列方案,每个方案占一行。

数据范围

1≤n≤7

输入样例:

复制代码
3

输出样例:

复制代码
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

解析与代码

那么对于这道题结合上面那张图我们就知道首先要从1出发,然后去遍历除了1的1-n其他数字,那么1就要有个状态,记录已经遍历过该数字了,1就要添加到路径之中。

后面去遍历其他数字,其他数字如果也遍历了也就是说在路径里面那么其实就没有必要去遍历了。因为是要全搜索,所以最后我们也一定要把原先遍历的去除掉,把状态删掉

java 复制代码
import java.util.*;

public class Main {
	static int n;
	static int[] path;
	static boolean[] state;
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		path = new int[n + 1];
		state = new boolean[n + 1];
		dfs(1);
	}
	public static void dfs(int u) {
		if(u > n) {
			for(int i = 1;i <= n;i ++) {
				System.out.print(path[i] + " ");
			}
			System.out.println();
			return;
		}
		for(int i = 1;i <= n;i ++) {
			if(!state[i]) {
				path[u] = i;
				state[i] = true;
				dfs(u + 1);
				state[i] = false;
			}
		}
		
	}
}

总结出一个框架

java 复制代码
result = [];
void dfs(路径, 选择列表) {
    if(满足结束条件):
        result.addd(路径);
        return;
    
    for 选择 in 选择列表 {
        做选择
        dfs(路径,选择列表)
        去除此选择
    }
}

n-皇后

这个图解思路我觉得写的很好,解答了为什么dg和udg要那么设置函数

java 复制代码
import java.util.*;
public class Main {
	static int n;
	static char[][] chs; // 答案
	static boolean[] col, dg, udg;  // 状态
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		chs = new char[n + 1][n + 1];
		col = new boolean[n + 10];
		dg = new boolean[n + 10];
		udg = new boolean[n + 10];
		for(int i = 0;i < n;i ++) {
			for(int j = 0;j < n;j ++) {
				chs[i][j] = '.';
			}
		}
		dfs(0);
	}
	public static void dfs(int x) {
		if(x == n) {
			for(int i = 0;i < n;i ++) {
				for(int j = 0;j < n;j ++) {
					System.out.print(chs[i][j]);
				}
				System.out.println();
			}
			System.out.println();
			return;
		}
		for(int y = 0;y < n;y ++) {
			if(!col[y] && !dg[y - x + n] && !udg[y + x]) {
				chs[x][y] = 'Q';
				col[y] = dg[y - x + n] = udg[y + x] = true;
				dfs(x + 1);
				chs[x][y] = '.';
				col[y] = dg[y - x + n] = udg[y + x] = false;
			}
		}
		
	}
}
相关推荐
oier_Asad.Chen5 分钟前
【洛谷题解/AcWing题解/OI学习笔记】洛谷P2868【USACO07DEC】Sightseeing Cows G(01分数规划求最大比率)
算法·图论·spfa·二分·负环
leisoo80972 小时前
财报数据怎么排雷本地化Python构建财务异常预警系统
人工智能·python·算法
luj_17684 小时前
塔防牌:策略与卡牌的智慧碰撞
服务器·c语言·开发语言·经验分享·算法
郝学胜-神的一滴5 小时前
干货版《算法导论》17:二叉树核心原理、遍历逻辑与高阶实操全解
数据结构·c++·python·算法·计算机·编程
爱编程的小新☆5 小时前
【LeetCode】从递归到 Flood Fill:5 道题吃透 DFS 的选择、回溯与标记
java·算法·leetcode·深度优先·回溯·flood fill
Water_Sunzhipeng5 小时前
2024牛客暑期多校训练营1
算法
hetao17338375 小时前
2026-08-09~08-14 hetao1733837 的刷题记录
c++·算法
技术小黑5 小时前
RNN算法实战系列06 | LSTM 实现糖尿病探索与预测
rnn·算法·lstm
疯狂打码的少年5 小时前
【数据结构】二叉树的性质(五大性质+计算)
数据结构·笔记·算法
wabs6666 小时前
关于图论【A*算法 | 卡码网127.骑士的攻击的思考】
数据结构·算法·图论·卡码网·广搜的改进版