(dfs)迷宫问题

一、题目 

题目描述 Description

给定一个 n*m 的迷宫,并且迷宫里有 t 处放置有障碍,不可通过有障碍的地方。在迷宫中移动有上下左右四种方式。
给定起点坐标和终点坐标,问有多少种从起点坐标到终点坐标的方案。

输入描述 Input Description

第一行n、m和t,n为行,m为列,t为障碍总数。
第二行起点坐标sx,sy,终点坐标fx,fy。
接下来t行,每行为障碍点的坐标。

输出描述 Output Description

给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方案总数。

样例输入 Sample Input

2 3 1 1 1 2 3 2 1

样例输出 Sample Output

2

数据范围及提示 Data Size & Hint

1≤N,M≤5

 二、程序

(1)搜索

看到 求方案总数就可以想到---深搜!

dfs模板:

void dfs(int x,int y){
    if(到达终点){
        cnt++;
        return ;//回溯
    }
    for(int i=0;i<4;i++){
        int dx=x+d[i][0];
        int dy=y+d[i][1];
        if(满足条件){
           搜索下一个(dx,dy)
        }
    }
}

在此题,终点:ex,ey

条件:dx>=1&&dx<=n&&dy>=1&&dy<=m&&!v[dx][dy]&&!a[dx][dy]

搜索,一般先标记,再搜,最后撤销标记

本题dfs:

void dfs(int x,int y){
    if(x==ex&&y==ey){
        cnt++;
        return ;
    }
    for(int i=0;i<4;i++){
        int dx=x+d[i][0];
        int dy=y+d[i][1];
        if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&!v[dx][dy]&&!a[dx][dy]){
            v[dx][dy]=1;
            dfs(dx,dy);
            v[dx][dy]=0;
        }
    }
}

(2)输入

本题输入有“亿”点不一样

普通:输入迷宫

本题:输入障碍

while循环直接搞定!

while(t--){
    cin>>E>>V;//输入障碍坐标
    a[E][V]=1;//标记
}

(3)解决

组合一下,注意d数组:{{-1,0},{0,1},{1,0},{0,-1}}

代码:

#include<iostream>
using namespace std;
int n,m,t,sx,sy,ex,ey,E,V,a[10][10],d[4][2]={{-1,0},{0,1},{1,0},{0,-1}},cnt;
bool v[10][10];
void dfs(int x,int y){
    if(x==ex&&y==ey){
        cnt++;
        return ;
    }
    for(int i=0;i<4;i++){
        int dx=x+d[i][0];
        int dy=y+d[i][1];
        if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&!v[dx][dy]&&!a[dx][dy]){
            v[dx][dy]=1;
            dfs(dx,dy);
            v[dx][dy]=0;
        }
    }
}
int main(){
    cin>>n>>m>>t>>sx>>sy>>ex>>ey;
    while(t--){
        cin>>E>>V;
        a[E][V]=1;
    }
    v[sx][sy]=1;
    dfs(sx,sy);
    cout<<cnt;
	return 0;
}

三、总结

本题注意 难点 while输入,是DFS模板题之一

DFS特点:可以求最短路径长度,耗时间

谢谢观看,Thanks♪(・ω・)ノ

如有不足,请指出

### 蓝桥杯 DFS 迷宫 Java 实现 #### 解题思路 对于迷宫问题,可以采用深度优先搜索(DFS算法来寻找从起点终点路径DFS是一种遍历或搜索树或图的算法,沿着树的深度遍历节点,尽可能深地搜索树的分支[^2]。 在处理迷宫问题时,通常会定义一个维数组表示迷宫的地图,其中`0`代表可以通过的道路,而`1`或其他特定数值则标记障碍物不可通过的位置。为了记录访问过的坐标位置并防止重复访问同一地点造成死循环,在程序内部还需要维护另一个同样大小的布尔型维数组用于跟踪已经探索过的地方。 当执行DFS函数调用时,除了传递当前所在的行列索引外,还应携带方向参数以便于控制前进的方向以及回溯操作。每当成功抵达目的地即结束条件满足的情况下,则说明找到了一条完整的通路;反之如果遇到边界越界、撞墙或是再次回到之前走过的格子,则需返回至上一步继续尝试其他可能的选择直至穷尽所有可能性为止。 以下是基于上述逻辑编写的Java版本DFS解决迷宫问题的具体实现: ```java public class MazeSolver { private static final int[][] directions = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左四个移动方向 /** * 使用DFS方法求解迷宫问题. */ public boolean solveMaze(int[][] maze) { if (maze == null || maze.length == 0 || maze[0].length == 0) return false; int rows = maze.length; int cols = maze[0].length; boolean[][] visited = new boolean[rows][cols]; return dfs(maze, visited, 0, 0); } private boolean dfs(int[][] maze, boolean[][] visited, int row, int col) { // 判断是否到达出口 if (row == maze.length - 1 && col == maze[row].length - 1) return true; // 标记当前位置已被访问 visited[row][col] = true; for (int[] dir : directions) { int newRow = row + dir[0], newCol = col + dir[1]; // 检查新位置合法性 if (!isValidPosition(newRow, newCol, maze, visited)) continue; // 尝试向该方向前进 if (dfs(maze, visited, newRow, newCol)) return true; } // 当前路径不通,恢复状态准备回退 visited[row][col] = false; return false; } private boolean isValidPosition(int r, int c, int[][] m, boolean[][] v) { return !(r < 0 || c < 0 || r >= m.length || c >= m[r].length || m[r][c] != 0 || v[r][c]); } } ``` 此代码片段展示了如何利用递归形式的DFS算法去探寻是否存在通往目标坐标的可行路线,并且包含了必要的辅助功能如验证下一步行动的有效性和初始化设置等细节。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值