递归、回溯和DFS的区别

  • 递归是一种算法结构,回溯是一种算法思想。
  • 一个递归就是在函数中调用函数本身来解决问题。
  • 回溯就是通过不同的尝试来生成问题的解,有点类似于穷举,但是和穷举不同的是回溯会“剪枝”。

剪枝的意思也就是说对已经知道错误的结果没必要再枚举接下来的答案了,比如一个有序数列1,2,3,4,5,我要找和为5的所有集合,从前往后搜索我选了1,然后2,然后选3的时候发现和已经大于预期,那么4,5肯定也不行,这就是一种对搜索过程的优化。

回溯搜索是深度优先搜索(DFS)的一种。对于某一个搜索树来说(搜索树是起记录路径和状态判断的作用),回溯和DFS,其主要的区别是,回溯法在求解过程中不保留完整的树结构,而深度优先搜索则记下完整的搜索树。

为了减少存储空间,在深度优先搜索中,用标志的方法记录访问过的状态,这种处理方法使得深度优先搜索法与回溯法没什么区别了。

递归的一般结构:

void f()  
{  
     if(符合边界条件)  
     {  
        ///////  
        return;  
     }  

     //某种形式的调用  
     f();  
}  

回溯的一般结构:

void DFS(int 当前状态)  
{  
      if(当前状态为边界状态)  
      {  
        记录或输出  
        return;  
      }  
      for(i=0;i<n;i++)       //横向遍历解答树所有子节点  
      {  
           //扩展出一个子状态。  
           修改了全局变量  
           if(子状态满足约束条件)  
            {  
              dfs(子状态)  
           }  
            恢复全局变量//回溯部分  
      }  
}  

BFS和DFS相似。BFS显式用队列,DFS隐式用栈,即递归。
当然,对于DFS,用递归可能会造成栈溢出,所以也可以更改为显示栈。

以下以走迷宫问题为力,做一下说明:

*表示可走
#表示障碍
T表示出口
入口是(1,1),数据保证左上角是入口。

#include<iostream>
using namespace std;

char maze[100][100];
bool flag[100][100];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int m,n;

bool dfs(int x,int y)
{
    flag[x][y]=1;              //走过的路标记为1
    if(maze[x][y]=='T')return true;
    for(int i=0;i<4;i++)       //四个方向
    {
        int nx=x+dx[i];
        int ny=y+dy[i];
        if(flag[nx][ny]==0||maze[nx][ny]=='*'||maze[nx][ny]=='T'&&nx>0&&ny>0&&nx<m+1&&ny<n+1)
        {
            return dfs(nx,ny);   
            flag[nx][ny]=0;    //回溯,将标记重新标记为0
        }
    }
    return false;             //找不到返回false
}

int main()
{

    while(cin>>m>>n){
    memset(maze,0,sizeof(maze));
    memset(flag,0,sizeof(flag));
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            cin>>maze[i][j];
    if(dfs(1,1))cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    }
}

参考文献:递归,回溯和DFS的区别迷宫问题递归,回溯,DFS,BFS的理解和模板

  • 36
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
下面给出一个基于递归回溯算法的C++代码实现: ```c++ #include <iostream> #include <vector> #include <stack> #include <ctime> #include <cstdlib> using namespace std; const int N = 1010; int n, m; // 迷宫的行数和列数 int maze[N][N]; // 迷宫地图 int vis[N][N]; // 标记是否访问过某个点 // 定义四个方向 int dx[4] = {-1, 0, 1, 0}; int dy[4] = {0, 1, 0, -1}; // 判断某个点是否在迷宫内 bool inMaze(int x, int y) { return x >= 0 && x < n && y >= 0 && y < m; } // 随机生成迷宫地图 void generateMaze() { srand(time(0)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { maze[i][j] = rand() % 2; // 随机生成0或1 } } maze[0][0] = maze[n - 1][m - 1] = 0; // 迷宫入口和出口不能是障碍物 } // 递归回溯求解迷宫 bool dfs(int x, int y) { if (x == n - 1 && y == m - 1) return true; // 找到出口 vis[x][y] = 1; // 标记当前点为已访问 for (int i = 0; i < 4; i++) { int nx = x + dx[i]; int ny = y + dy[i]; if (inMaze(nx, ny) && maze[nx][ny] == 0 && !vis[nx][ny]) { // 判断是否可以走到下一个点 if (dfs(nx, ny)) return true; // 递归搜索下一个点 } } return false; // 找不到出口 } int main() { cin >> n >> m; generateMaze(); cout << "迷宫地图:" << endl; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cout << maze[i][j] << " "; } cout << endl; } cout << "是否有解:" << (dfs(0, 0) ? "是" : "否") << endl; return 0; } ``` 在这个代码中,我们先随机生成一个迷宫地图,然后从入口开始使用递归回溯算法搜索迷宫。在搜索过程中,我们使用一个二维数组 `vis` 记录每个点是否访问过,确保不会重复访问同一个点。如果找到了出口,则返回 true;否则,返回 false。最后输出是否有解。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值