DFS算法

bool visit[];
void dfs(){
     if(返回条件 == true){
     return;
     }
     if(!visit[i]){
     visit[i] = true;
     //operation1
     dfs();
     //operation2
     visit[i] = false;
     }
     return;
}
void dfs(int x,int y,int z)//坐标,层次/步数
{
    if (z.../坐标达到条件)//终止条件
    {
        执行
        return;
    }
    for (int i = 0; i < 可扩展的路径数; i++)//遍历
    {
        if (符合条件)
        {
            flag=1;
            dfs(下一种情况);
            flag=0;//回溯
        }
    }
}    
用path 数组保存排列,当排列的长度为 n 时,是一种方案,输出。
用st 数组表示数字是否用过。当st[i]为true 时,i 已经被用过了,st[i] 为 false 时,i 没被用过。
dfs(i) 表示的含义是:在path[i] 处填写数字,然后递归的在下一个位置填写数字。
回溯:第 i 个位置填写某个数字的所有情况都遍历后, 第 i 个位置填写下一个数字。
#include<iostream>
 
using namespace std;
 
const int N = 10;
int path[N];
bool st[N];//标注数字是否被用过
int n;
 
void dfs(int x)
{
    if(x == n)//数字填完了,输出,走到第n个位置
    {
        for(int i = 0; i < n; i ++)  printf("%d ", path[i]);
        puts("");
        return;
    }
    
    for(int i = 1; i <= n; i ++)//这里是空位上可以选择的数字为:1 ~ n
     if(!st[i])//如果数字 i 没有被用过
     {
        path[x] = i;//放入空位
        st[i] = true;//放入空位,则数字被用,修改状态
        dfs(x + 1);//填下一个位
        st[i] = false;//回溯,恢复现场,数字i后续可用
     }
}
 
int main()
{
    cin >> n;
    dfs(0);// 在path[0]处开始填数
    
    return 0;
}

迷宫问题——迷宫从起点到终点有没有路径,有几条,求最短路径

(深搜暴搜)https://www.bilibili.com/video/BV1uR4y1s7FA?vd_source=cecc6ff6e883f42b10c1d53026d0846e

题目描述

w设有一个N*N(2<=N<10)方格的迷宫,入口和出口分别在左上角和右上角。迷宫格子中分别放0和1,0表示可通,1表示不能,入口和出口处肯定是0。迷宫走的规则如下所示:即从某点开始,有八个方向可走,前进方格中数字为0时表示可通过,为1时表示不可通过,要另找路径。找出所有从入口(左上角)到出口(右上角)的路径(不能重复),输出路径总数,如果无法到达,则输出0。

输入

第一行输入一个整数n

然后是n行,每行n个数,分别为0 或1

输出

输出一个整数表示路径数

样例输入

3
0 0 0
0 1 1
1 0 0

样例输出

2
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

bool a[20][20];
int n,ans=0;
int dx[9]={0,-1,-1,-1,0,0,1,1,1};
int dy[9]={0,-1,0,1,-1,1,-1,0,1};

void dfs(int cx,int cy)//从cx cy出发 
{
    if (cx==1&&cy==n)//从cx xy出发,发现就是目标结点, 
    {
        ans++;
        return ;// 返回调用该函数的上一层 
    }
    for(int i=1;i<=8;i++)
    {
         //cx cy方向数组变换
         int tx=cx+dx[i];
         int ty=cy+dy[i]; 
         if(tx>=1&&tx<=n&&ty>=1&&ty<=n&&a[tx][ty]==0)//遍历,不能越界 ,并且能通行 
         {
             a[tx][ty]=1;//标记 
             dfs(tx,ty);//搜索 
             a[tx][ty]=0;//取消标记 
        } 
    }
    return;
} 
 
int main()
{
    cin>>n;  //初始化地图
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cin>>a[i][j];
        }
    }
    a[1][1]=1;//访问数组,0表示未访问,1表示访问,默认为0,表示从11点出发,不能再回到11点 
    dfs(1,1);//开始搜索
    cout<<ans<<endl;//所有路径搜完,打印
    return 0; 
}

连通块——踏青

蒜头君和他的朋友周末相约去召唤师峡谷踏青。他们发现召唤师峡谷的地图是由一块一块格子组成的,有的格子上是草丛,有的是空地。草丛通过上下左右 4个方向扩展其他草丛形成一片草地,任何一片草地中的格子都是草丛,并且所有格子之间都能通过上下左右连通。如果用’#‘代表草丛,’.'代表空地,下面的峡谷中有 2 片草地。

##..
..##

处在同一个草地的 2 个人可以相互看到,空地看不到草地里面的人。他们发现有一个朋友不见了,现在需要分头去找,每个人负责一片草地,蒜头君想知道他们至少需要多少人。

输入格式

第一行输入 n, m (1≤n,m≤100)表示峡谷大小。

接下来输入 n行字符串表示峡谷的地形。

输出格式

输出至少需要多少人。

样例输入

5 6
.#....
..#...
..#..#
...##.
.#....

样例输出

5

想法:求人->求草地片数,两个草丛->草地

输入地图,对于每个未标记的草丛#,四个方向递归,搜索完毕之后得到一片草地,这片草地只需要一个人,不需要把标记还原,(然后再从未被标记过的草丛处开始搜索,遇到未标记的草丛则标记,遇到空地则返回),然后从该草丛处开始搜索来确定有多少草丛与该草丛直接或间接相连,即重复上述步骤,直到所有的草丛都被搜过。

#include <iostream>
using namespace std;
int n, m, ans = 0;
char map[105][105];
bool vis[105][105];
int dx[5] = {0, 1, 0, -1, 1};
int dy[5] = {0, 1, 0, -1, 0};
void dfs(int x, int y) { //从x y出发
 if (x < 0 || x >= n || y < 0 || y >= m || vis[x][y] == 1 || map[x][y] == '.') {
  return;
 }
 vis[x][y] = 1;
 for (int i = 1; i <= 4; i++) {
  //x y方向数组变换
  int tx = x + dx[i];
  int ty = y + dy[i];
  if (tx >= 0 && tx < n && ty >= 0 && ty < m && vis[tx][ty] == 0) { //遍历,不能越界 ,并且能通行
   vis[tx][ty] = 1; //标记
   dfs(tx, ty); //搜索
  }
 }
}
int main() {
 cin >> n >> m; //初始化地图
 for (int i = 0; i < n; i++) {
  for (int j = 0; j < m; j++) {
   cin >> map[i][j];
  }
 }
 //开始搜素
 for (int i = 0; i < n; i++) {
  for (int j= 0; j < m; j++) {
   if (map[i][j] == '#' && vis[i][j] == 0) { //条件:草丛,并且没访问过
        //    vis[i][j] = 1; //标记
    dfs(i, j); //开始搜索
    ans++;//草丛数量++
   }
  }

 }
 cout << ans << endl;
 return 0;
}

迷宫解的方案数

题目描述:

问,在不走重复路径的情况下,总共有多少不同可以到达终点的路径呢?蒜头君稍加思索便给出了答案,你要不要也来挑战一下?

输入格式:

第一行输入两个整数 n(1≤n≤11), m(1≤m≤11),表示迷宫的行和列。

然后有一个n×m 的地图,地图由’.’、’#’、‘s’、‘e’这四个部分组成。’.‘表示可以通行的路,’#'表示迷宫的墙,'s’表示起始点,'e’表示终点。

输出格式

输出一个整数,表示从’s’到达’e’的所有方案数。

样例输入

5 5
s####
.####
.####
.####
....e

样例输出

1

思路:找到所有解,所以要取消标志

#include<iostream>
using namespace std;
int n,m,ans;
char map[20][20];
bool vis[20][20];
int dx[5]={0,1,0,-1,0};
int dy[5]={0,0,-1,0,1}; 

void dfs(int x,int y) {
    if(x < 0 || x >= n || y < 0 || y >= m || vis[x][y] == 1 || map[x][y] == '#'){
        return;// 返回调用该函数的上一层 
    }
    if(map[x][y]=='e'){
        ans++;
        return;
    }
    vis[x][y]==1;
    for(int i=1;i<=4;i++)//方向数组变换 
    {
        int cx=x+dx[i];
        int cy=y+dy[i];
        if( map[x][y] == 'e'){
            vis[cx][cy]=1;//标记
            dfs(cx,cy); 
            vis[cx][cy]=0;
            ans++;
        }
    }
}

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
        cin>>map[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
        if(map[i][j]=='s'){ //条件:从起点开始搜索 
            ans++;
            dfs(i,j);
            
          }
        }
    }
    cout << ans << endl;
    return 0;
} 

打印路径——马走日

#include<bits/stdc++.h>
using namespace std;
int x[10],y[10],s; //每找到一个点,就记录,且节点数不会超过列数9 
bool vis[5][9];
int dx[5]={0,2,1,-1,-2};
int dy[9]={0,1,2,2,1};
void dfs(int cx, int cy,int cur)//cur表示(cx,cy)是第几个节点
{
    
    x[cur]=cx;y[cur]=cy;//记录
    if(cx==4&&cy==8)
    {
        s++;
        cout<<s<<":0,0";
        for(int i=2;i<=cur;i++){
        cout<<"->"<<x[i]<<","<<y[i];
        }
        cout<<endl;
        return;
     } 
     for(int i=0;i<=4;i++)
     {
         int tx=cx+dx[i];
         int ty=cy+dy[i];
         if(tx>=0&&tx<=4&&ty>=0&&ty<=8&&vis[tx][ty]==0)
         {
             vis[tx][ty]=1;
             dfs(tx,ty,cur+1);
             vis[tx][ty]=0;
         }
     }
 } 

int main()
{ 
    vis[0][0]=1; 
    dfs(0,0,1);//从00点出发(0,0)作为第一个节点去搜下一个节点 
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DFS算法(深度优先搜索算法,Depth-First Search)是一种常用的图搜索算法,用于遍历或搜索图或树的所有节点。DFS算法通过递归的方式实现,在搜索过程中优先探索深度,直到到达叶节点再回溯。 在MATLAB中实现DFS算法,可以采用如下步骤: 1. 创建一个函数,用于实现DFS算法。命名为dfs。 2. 设置输入参数,例如起始节点和目标节点。 3. 初始化一个栈数据结构,用于保存待搜索的节点。 4. 初始化一个集合,用于保存已访问的节点。 5. 将起始节点压入栈中,并标记为已访问。 6. 当栈不为空时,执行以下步骤: a. 弹出栈顶节点,将其标记为已访问。 b. 如果当前节点是目标节点,则搜索完成,返回。 c. 如果当前节点不是目标节点,则获取其所有邻接节点。 d. 遍历邻接节点: - 如果邻接节点没有被访问过,则压入栈中,并标记为已访问。 e. 重复步骤6直到栈为空。 7. 如果栈为空仍未找到目标节点,则搜索失败,返回。 使用DFS算法可以解决很多与图相关的问题,例如寻找图中路径,判断图的连通性等。在实际应用中,可以根据具体的问题进行相应的修改和优化,以适应不同的需求。 需要注意的是,在实际编写代码时,应该考虑避免重复访问节点,避免死循环,以及处理异常情况。另外,对于复杂的图结构,可能需要使用其他数据结构或算法进行优化,以提高搜索效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值