dfs算法经典例题

这是一篇关于使用深度优先搜索(DFS)解决Oil Deposits问题的博客。内容涉及如何通过DFS算法来寻找并标记潜在的石油储藏区域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Oil Deposits

#include<stdio.h>

#include<string.h>
int m,n,sum;
char map[102][102];
int dir[8][2]= {0,1,0,-1,1,0,-1,0,-1,-1,1,1,-1,1,1,-1};
void dfs(int i,int j)
{
    for(int s=0; s<8; s++)
    {
        int di=i+dir[s][0];
        int dj=j+dir[s][1];
        if(di<0||dj<0||di>=m||dj>=n||map[di][dj]=='*')
            continue;
        map[di][dj]='*';
        dfs(di,dj);
    }
}
int main()
{
    while(~scanf("%d%d",&m,&n))
    {
        sum=0;
        for(int i=0; i<m; i++)
               scanf("%s",map[i]);
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
                if(map[i][j]=='@')
                {
                    map[i][j]='*';
                    dfs(i,j);
                    sum++;
                }
        printf("%d\n",sum);
    }
    return 0;
}
<think>嗯,用户问的是DFS的回溯算法有没有经典例题。首先,我得回忆一下DFS和回溯的关系。回溯算法通常用递归实现,而DFS是一种遍历方式,回溯常和DFS结合使用,用于解决需要试探和撤销选择的问题。 首先想到的经典例题应该是八皇后问题。这个问题要求在棋盘上放置八个皇后,使得它们互不攻击。这需要逐行放置,并检查每一列和对角线是否冲突。每次放置后递归到下一行,如果冲突就回溯。 然后是数独问题。需要填充数字,满足每行、每列和每个子九宫格都包含1-9不重复。回溯在这里用于尝试填入数字,如果发现冲突就回退,继续尝试其他可能。 全排列问题也是典型的回溯应用。比如生成一个数组的所有排列,通过交换元素位置,递归处理后续位置,再撤销交换进行回溯。 组合总和问题,比如给定数组和一个目标数,找出所有和为目标的组合。回溯时记录当前路径,尝试每个数字,超过目标则回溯,找到解则保存路径。 括号生成问题,生成所有有效括号组合。回溯过程中保证左右括号数量有效,比如左括号数不超过n,右括号不超过左括号数。 这些例题都涉及穷举可能的解,并通过剪枝减少无效搜索。用户可能需要具体的步骤说明,比如问题描述、解决思路、代码框架和复杂度分析。需要确保回答结构清晰,分点说明每个例题,帮助用户理解回溯的应用场景和实现方法。同时注意使用正确的中文术语和LaTeX格式的数学表达式,比如用$O(n!)$表示复杂度。</think>DFS的回溯算法是解决组合、排列、搜索等问题的经典方法,以下是几个经典例题及其解析: --- ### **1. 八皇后问题(N-Queens)** **问题描述** 在$N \times N$的棋盘上放置$N$个皇后,使得它们互不攻击(即不在同一行、列或对角线)。 **解决思路** - 逐行放置皇后,每行只能放一个。 - 检查当前列和对角线是否冲突。 - 若冲突则回溯,尝试其他位置。 **代码框架** ```python def solveNQueens(n): def backtrack(row, cols, diag1, diag2): if row == n: res.append(["".join(r) for r in board]) return for col in range(n): d1 = row - col # 主对角线特征值 d2 = row + col # 副对角线特征值 if col not in cols and d1 not in diag1 and d2 not in diag2: board[row][col] = 'Q' backtrack(row + 1, cols | {col}, diag1 | {d1}, diag2 | {d2}) board[row][col] = '.' # 回溯 res = [] board = [['.'] * n for _ in range(n)] backtrack(0, set(), set(), set()) return res ``` **复杂度** 最坏情况为$O(n!)$,通过剪枝优化实际复杂度更低。 --- ### **2. 数独问题(Sudoku Solver)** **问题描述** 填充数独的空格,使每行、每列和每个$3 \times 3$子九宫格均包含数字$1-9$不重复。 **解决思路** - 遍历每个空格,尝试填入$1-9$。 - 检查行、列、子九宫格是否合法。 - 若后续无法填充则回溯。 **代码框架** ```python def solveSudoku(board): def backtrack(pos): if pos == 81: return True i, j = pos // 9, pos % 9 if board[i][j] != '.': return backtrack(pos + 1) for num in '123456789': if isValid(i, j, num): board[i][j] = num if backtrack(pos + 1): return True board[i][j] = '.' # 回溯 return False def isValid(row, col, num): for k in range(9): if board[row][k] == num or board[k][col] == num: return False r, c = row // 3 * 3, col // 3 * 3 for x in range(3): for y in range(3): if board[r + x][c + y] == num: return False return True backtrack(0) ``` --- ### **3. 全排列(Permutations)** **问题描述** 给定一个无重复元素的数组,返回所有可能的排列。 **解决思路** - 通过交换元素生成不同排列。 - 递归处理后续位置,完成后撤销交换。 **代码框架** ```python def permute(nums): def backtrack(first): if first == n: res.append(nums[:]) return for i in range(first, n): nums[first], nums[i] = nums[i], nums[first] # 试探 backtrack(first + 1) nums[first], nums[i] = nums[i], nums[first] # 回溯 n = len(nums) res = [] backtrack(0) return res ``` --- ### **4. 组合总和(Combination Sum)** **问题描述** 给定候选数组和一个目标数,找出所有和为目标的组合(可重复使用元素)。 **解决思路** - 记录当前路径,递归尝试每个候选数。 - 若超过目标则剪枝,等于目标则保存结果。 **代码框架** ```python def combinationSum(candidates, target): def backtrack(start, path, remain): if remain == 0: res.append(path[:]) return for i in range(start, len(candidates)): if candidates[i] > remain: continue # 剪枝 path.append(candidates[i]) backtrack(i, path, remain - candidates[i]) # 可重复使用元素 path.pop() # 回溯 res = [] candidates.sort() backtrack(0, [], target) return res ``` --- ### **5. 括号生成(Generate Parentheses)** **问题描述** 给定数字$n$,生成所有有效的$n$对括号组合。 **解决思路** - 保证左括号数不超过$n$,右括号数不超过左括号数。 - 递归添加左/右括号,完成后回溯。 **代码框架** ```python def generateParenthesis(n): def backtrack(s, left, right): if len(s) == 2 * n: res.append(s) return if left < n: backtrack(s + '(', left + 1, right) # 添加左括号 if right < left: backtrack(s + ')', left, right + 1) # 添加右括号 res = [] backtrack("", 0, 0) return res ``` --- ### **总结** 回溯算法的核心是: 1. **试探选择**:在每一步尝试一个候选解。 2. **递归搜索**:进入下一层决策树。 3. **撤销选择**(回溯):若当前路径无解,回退到上一步。 这些例题均通过DFS遍历解空间,并通过剪枝减少无效搜索,是理解回溯算法经典
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值