走迷宫 II

强化学习之DQN:算法思想、案例及详解,使用DQN算法实现自动走迷宫 DQN算法及案例:如何使用DQN实现走迷宫算法原理案例详解 算法原理 在了解DQN之前,我们需要知道值函数近似这一思想。 值函数近似:在数据较大情况下,根据s&a去查询Q值会比较困难。值函数近似是输入s和a,近似地计算得到Q值,在DQN中使用的是神经网络完成这一步骤,简单情况下使用线性函数也行。 DQN:融合神经网络和Q值。Q值难以记录,可以通过神经网络输入s、a,然后输出Q值进行策略的选择。前面提到的算法训练目标是Q矩阵,DQN训练目标训练一个神经网络,可以通过这个网络来计算得到Q值并选择最优动作 阅读详情

题目描述

迷宫地宫地形信息记录于一维字符串数组 maze 中,maze[i] 为仅由 "."、"X"、"S" 和 "E" 组成的字符串,其中:

  • "X" 表示墙,不可直接通行,但可选择将墙推倒后通过;
  • "." 表示空地,可以通行;
  • "S" 表示迷宫入口;
  • "E" 表示迷宫出口。

请你求出入口到出口所需的最少推墙次数。

注意: 迷宫中仅有一个入口和一个出口。

示例 1:

输入:
maze = ["XSXX","....","XXX.","X.E."]

输出: 0

解释:
不需要推倒任何墙就可以直接从入口到达出口,下图是一种可行的方案:

示例 2:

输入:
maze = ["XSXX","X...","XX..","EX.."]

输出: 1

解释:
最少需要推倒 1 次墙,下图是一种可行的方案:

提示:

  • 1 <= maze.length, maze[i].length <= 100

问题分析

这是一个带权重的最短路径问题,具有以下特点:

  • 移动规则:
    • 移动到空地(".")或出口("E"):代价为 0
    • 推倒墙("X")并移动:代价为 1
  • 目标:找到从入口("S")到出口("E")的最小推墙次数
  • 算法选择:
    • 由于只有两种权重(0和1),最适合使用 0-1 BFS
    • 也可以使用 Dijkstra 算法

解题思路

0-1 BFS 方法

核心思想:

  • 使用双端队列(Deque)
  • 代价为0的移动加入队列头部
  • 代价为1的移动加入队列尾部
  • 这样保证每次取出的都是当前代价最小的状态

算法步骤:

  1. 找到起点和终点位置
  2. 使用双端队列进行BFS
  3. 对于每个位置,尝试向四个方向移动
  4. 根据目标位置的类型决定代价和入队方式

解法实现

Java 实现

import java.util.ArrayDeque;
import java.util.Deque;

/**
 * 3. 走迷宫 II
 * 0-1 BFS
 */
class Solution {

    // 四个方向:上下左右
    private static final int[][] DIRS = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

    public int solve(String[] maze) {
        int rows = maze.length;
        int cols = maze[0].length();

        // 找到起点和终点
        int startRow = -1, startCol = -1;
        int endRow = -1, endCol = -1;

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (maze[i].charAt(j) == 'S') {
                    startRow = i;
                    startCol = j;
                }
                if (maze[i].charAt(j) == 'E') {
                    endRow = i;
                    endCol = j;
                }
            }
        }

        return bfs(maze, startRow, startCol, endRow, endCol);
    }

    private int bfs(String[] maze, int startRow, int startCol, int endRow, int endCol) {
        int rows = maze.length;
        int cols = maze[0].length();

        // 距离数组,记录到达每个位置的最少推墙次数
        int[][] dist = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                dist[i][j] = Integer.MAX_VALUE;
            }
        }

        // 双端队列用于0-1 BFS
        Deque<int[]> deque = new ArrayDeque<>();
        deque.offer(new int[]{startRow, startCol});
        dist[startRow][startCol] = 0;

        while (!deque.isEmpty()) {
            int[] cur = deque.poll();
            int curRow = cur[0];
            int curCol = cur[1];

            // 如果到达终点,返回结果
            if (curRow == endRow && curCol == endCol) {
                return dist[curRow][curCol];
            }

            // 尝试四个方向
            for (int[] dir : DIRS) {
                int newRow = curRow + dir[0];
                int newCol = curCol + dir[1];

                // 检查边界
                if (newRow < 0 || newRow >= rows || newCol < 0 || newCol >= cols) {
                    continue;
                }

                char cell = maze[newRow].charAt(newCol);
                int newCost;

                // 计算移动代价
                if (cell == '.' || cell == 'E') {
                    newCost = dist[curRow][curCol]; // 移动到空格或终点,代价不变
                } else if (cell == 'X') {
                    newCost = dist[curRow][curCol] + 1; // 移动到墙,代价加1
                } else {
                    continue; // 遇到其他字符,跳过
                }

                // 如果找到更优路径,更新距离并加入队列
                if (newCost < dist[newRow][newCol]) {
                    dist[newRow][newCol] = newCost;

                    // 0-1 BFS的关键:根据代价决定加入队列的位置
                    if (cell == '.' || cell == 'E') {
                        deque.offerFirst(new int[]{newRow, newCol}); // 代价为0,加入队列头部
                    } else {
                        deque.offerLast(new int[]{newRow, newCol}); // 代价为1,加入队列尾部
                    }
                }
            }
        }

        // 无法到达终点
        return -1;
    }
}

C# 实现

/**
 * 3. 走迷宫 II
 * 0-1 BFS
 */
public class Solution
{
    // 四个方向:上下左右
    private int[,] _dirs = new int[,] { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };

    public int Solve(string[] maze)
    {
        int rows = maze.Length;
        int cols = maze[0].Length;

        // 找到起点和终点
        int startRow = -1, startCol = -1;
        int endRow = -1, endCol = -1;
        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                if (maze[i][j] == 'S')
                {
                    startRow = i;
                    startCol = j;
                }
                else if (maze[i][j] == 'E')
                {
                    endRow = i;
                    endCol = j;
                }
            }
        }

        return Bfs(maze, startRow, startCol, endRow, endCol);
    }

    private int Bfs(string[] maze, int startRow, int startCol, int endRow, int endCol)
    {
        int rows = maze.Length;
        int cols = maze[0].Length;

        // 距离数组,记录到达每个位置的最少推墙次数
        int[,] dist = new int[rows, cols];
        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                dist[i, j] = int.MaxValue;
            }
        }

        // 双端队列用于0-1 BFS
        LinkedList<(int, int)> deque = new LinkedList<(int, int)>();
        deque.AddLast((startRow, startCol));
        dist[startRow, startCol] = 0;

        while (deque.Count > 0)
        {
            (int, int) cur = deque.First.Value;
            deque.RemoveFirst();
            
            int curRow = cur.Item1;
            int curCol = cur.Item2;

            // 如果到达终点,返回结果
            if (curRow == endRow && curCol == endCol)
            {
                return dist[curRow, curCol];
            }

            // 尝试四个方向
            for (int i = 0; i < 4; i++)
            {
                int newRow = curRow + _dirs[i, 0];
                int newCol = curCol + _dirs[i, 1];
                // 检查边界
                if (newRow < 0 || newRow >= rows || newCol < 0 || newCol >= cols)
                {
                    continue;
                }

                char cell = maze[newRow][newCol];
                // 计算移动代价
                int newCost;
                if (cell == '.' || cell == 'E')
                {
                    newCost = dist[curRow, curCol]; // 移动到空格或终点,代价为当前代价
                }
                else if (cell == 'X')
                {
                    newCost = dist[curRow, curCol] + 1; // 移动到墙,代价为当前代价加1
                }
                else
                {
                    continue; // 忽略其他字符
                }

                // 如果找到更优路径,更新距离并加入队列
                if (newCost < dist[newRow, newCol])
                {
                    dist[newRow, newCol] = newCost;

                    // 0-1 BFS的关键:根据代价决定加入队列的位置
                    if (cell == '.' || cell == 'E')
                    {
                        deque.AddFirst((newRow, newCol)); // 移动到空格或终点,加入队列头部
                    }
                    else
                    {
                        deque.AddLast((newRow, newCol)); // 移动到墙,加入队列尾部
                    }
                }
            }
        }

        return -1;
    }
}

算法复杂度分析

时间复杂度: O(M × N)

  • M 和 N 分别是迷宫的行数和列数
  • 每个位置最多被访问一次

空间复杂度: O(M × N)

  • 需要 dist 数组存储到达每个位置的最小代价
  • 双端队列在最坏情况下可能存储所有位置
用Python编写迷宫游戏 文章目录1、 项目概述1.1 项目目标和主要内容1.2 项目的主要功能2、 项目设计2.1项目总体框架2.2 关键算法分析3、设计步骤3.1导入模块3.2定义颜色变量3.3定义游戏结束函数3.4定义主函数3.5执行主函数3.6将.py文件转为.exe文件4、运行结果 1、 项目概述 1.1 项目目标和主要内容 迷宫游戏是非常经典的游戏,在该项目要求随机生成一个迷宫,并求解迷宫 1.2 项目的主要功能 随机生成迷宫并求解 2、 项目设计 2.1项目总体框架 通过 Prim 算法随机创建迷宫 阅读详情

相关推荐

小球走迷宫小游戏

import pygame import random import sys from pygame.locals import* pygame.init() screen = pygame.display.set_mode((680,640),0,32) red = 255,0,255 green = 0,255,0 def print_text(src,font,x,y,text,color=green): imgText = font.render(text,True,color) src.blit(

weixin_60413186的博客 3095

走迷宫2(穿墙) C/C++

18440 走迷宫2 时间限制:1000MS 代码长度限制:10KB 提交次数:0 通过次数:0 题型: 编程题 语言: G++;GCC;VC Description 有一个N*M(N,M<=10)的格子迷宫,1代表该格子为墙,不能通过,0代表可以通过,人在迷宫中可以尝试上下左右 个方向移动。 另外,在迷宫中如果从左边走出迷宫会回到迷宫最右边一格(只要该格不是墙),行不变,同样,从右边走出迷宫会 回到迷宫最左边一格,向上走出迷宫会回到迷宫最下边一格,向下走出迷宫会回到迷宫最上边一格。 现在给定

m0_52463794的博客 512

基于JAVA的简单迷宫游戏

迷宫游戏是非常经典的游戏,在该题中要求随机生成一个迷宫,并求解迷宫。基于Java的迷宫

cdh4119_的博客 4639

老鼠走迷宫II

由于迷宫的设计,老鼠走迷宫的入口至出口路径可能不止一条,如何求出所有的路径呢?   解法求所有的路径困哪起来复杂但其实更简单,只要在老鼠走到出口时显示经过的路径,然后退回上一格重新选择下一个位置继续递回就可以了,比求出单一路径更简单,程序只需要做一点点修改就行了。   /* *内容;老鼠走迷宫II *时间;3/01/2013 */ #include // 注:二维数组,根

holymaple的专栏 1449

走迷宫算法 用python实现

一个迷宫搜索的过程可以用python语言的算法来加以描述: 思路:穷举法。把所有的路都走了,总一条是对的。 首先老鼠不走回头路,它随便沿着一个方向一直走,遇到墙壁后换一个方向,直到没有路可以走,那么这条路就是死路。 然后,老鼠开始回退,一直回退到下一个路口,在沿着这条路一直走,以此类推,若存在到达出口的路,那么老鼠一定能走到出口。(因为最差的情况下,老鼠会把所有能走的路走一遍。) 用堆栈记录老鼠...

qq_40518671的博客 3704

[Deep Q Learning] pytorch 从零开始建立一个简单的DQN--走迷宫游戏

关于DQN的原理我不在这里说明了,如果对DQN的原理不了解可以去看我这个帖子 https://blog.csdn.net/mahuatengmmp/article/details/100627005 对DQN的伪代码做了翻译和分析 环境: pytorch opencv numpy 首先建立一个游戏环境 我是拿opencv做的显示效果,也可以不用opencv,具体因人而异 场景 首先需要建立一个游...

mahuateng的博客 1万+

7-4 走迷宫II(Dijkstra 算法)

最短路算法

asasa666的博客 1671

Python数据结构:堆栈——老鼠走迷宫

问题:有一只老鼠被困在迷宫之中了,我们需要实现一个算法,帮助老鼠走出迷宫。 已知迷宫矩阵为: MAZE=[[1,1,1,1,1,1,1,1,1,1,1,1],\ [1,0,0,0,1,1,1,1,1,1,1,1],\ [1,1,1,0,1,1,0,0,0,0,1,1],\ [1,1,1,0,1,1,0,1,1,0,1,1],\ [1,1,1,0,0,...

LiQingBB的博客 2119

程序设计基础II-实验 6 动态规划 7-2 走迷宫

有一个mn格的迷宫(表示有m行、n列),其中有可走的也有不可走的,如果用1表示可以走,0表示不可以走,输入这mn个数据和起始点、结束点(起始点和结束点都是用两个数据来描述的,分别表示这个点的行号和列号)。现在要你编程找出所有可行的道路,要求所走的路中没有重复的点,走时只能是上下左右四个方向。如果一条路都不可行,则输出相应信息(用-1表示无路)。

m0_73688552的博客 313

深度优先搜索走迷宫+SDL可视化

https://apriljia.com/2018/07/18/%E6%B7%B1%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2%E8%B5%B0%E8%BF%B7%E5%AE%ABsdl%E5%8F%AF%E8%A7%86%E5%8C%96/ 走迷宫问题是指在给定地图中,从寻找一条从起点(设为左上角)到终点(设为右下角)的路径的问题。假设迷宫形状如下...

mingzhiqing的博客 3552

【ACM】63. 不同路径 II(何时回溯?何时dp?)(初始化时,遇到障碍物直接break,因为不能向上或向左走;递推时,遇到障碍物直接continue(或者将dp[i][j]设置为0))

63. 不同路径 II https://leetcode-cn.com/problems/unique-paths-ii/ package com.LeetCode_ACM; import java.util.Scanner; public class lc63 { public static void main(String[] args){ Scanner in = new Scanner(System.in); int m = in.nextInt();

qq_60225495的博客 147

【笔试强训】Week5:空调遥控, kotor和气球,走迷宫,主持人调度II,体操队形,二叉树的最大路径和,排序子序列,消减整数

本文摘要了三道算法题的解题思路和代码实现: 空调遥控问题:通过排序数组后使用滑动窗口或二分查找,找到满足温度差不超过2p的最大连续区间。滑动窗口解法时间复杂度为O(n log n)。 kotori和气球问题:排列组合问题,第一个气球有n种选择,后续每个有n-1种选择,结果对109取模。 走迷宫问题:使用BFS求最短路径,处理输入时注意下标从1开始,遇到目标点时立即返回当前步数。 主持人调度问题未提供具体内容。各题解均包含Java代码实现,展示了不同算法思想的应用。

记录了从0学习Java技术栈的日常 394

经典强化学习 | 基于Q-Learning的机器人走迷宫

在机器人走迷宫中,机器人需要避开所有障碍从起点到达终点。本文基于Q-Learning来实现机器人走迷宫游戏的自主探索与学习

FRIGIDWINTER的博客 6829

bfs

1061: 走迷宫 II时间限制: 1 Sec  内存限制: 128 MB    Special Judge提交: 68  解决: 6[提交][状态][讨论版]题目描述上次zdw已经经历过一次走迷宫类的问题了, 但这次他又碰到了一个新的问题:还是在一个迷宫中寻宝, 不同的是, 当zdw试图走向迷宫外的时候(如果没有墙)....他将会从迷宫的另一边出现! 这个迷宫的边界原来是个传送门!那么给出迷宫大...

ACM_e的博客 556

网络变压器等效电路及网络变压器中间抽头作用详解

       华强盛电子导读:要详细了解网络变压器周边EMC管控及网络变压器BOB-SMITH电路的连接原理,首先我们对网络变压器的认识及其电路各参数影响都要有个简要的认识,本文,对非理想网络变压器等效电路做一个详细的分析,其中重点讨论一下网络变压器中间抽头的作用其影响                          网络变压器等效电路及                        ...

网络变压器专业资料 6006

别再对着ACF/PACF图发懵了!用R语言实战教你一眼分清AR、MA和ARMA模型

本文通过R语言实战详细解析了时间序列分析中AR、MA和ARMA模型的特征图识别技巧。重点讲解了如何通过ACF和PACF图的截尾与拖尾特征快速判断模型类型,帮助数据分析师建立从图形到模型的直觉映射,提升时间序列分析的效率和准确性。

weixin_28706923的博客 356

lintcode788. 迷宫II

题目 描述 在迷宫中有一个球,里面有空的空间和墙壁。球可以通过滚上,下,左或右移动,但它不会停止滚动直到撞到墙上。当球停止时,它可以选择下一个方向。 给定球的起始位置,目标和迷宫,找到最短距离的球在终点停留。距离是由球从起始位置(被排除)到目的地(包括)所走过的空空间的数量来定义的。如果球不能停在目的地,返回-1。 迷宫由二维数组表示。1表示墙和0表示空的空间。你可以假设迷宫的边界都是墙。开始和目标坐标用行和列索引表示。 1.在迷宫中只有一个球和一个目的地。 2.球和目的地都存在于一个空的空间中,它们最初不

weixin_44012730的博客 291

FI 应计对象的创建和摊销

创建/修改:ACACTREE01/ACACTREE02 应计对象的过账:ACACPOSTING

nancyln9711的博客 903

走迷宫

package com.supermars.practice; import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; public class 走迷宫 {     /*no     1为空地     0为障碍物     input     1 1 0 1 1

阿利在努力 1297

Android——Handler详解

1. 简介 Handler是一套 Android 消息传递机制 可以说只要有异步线程与主线程通信的地方就一定会有 Handler。 在多线程的应用场景中,将工作线程中需更新UI的操作信息 传递到 UI主线程,从而实现 工作线程对UI的更新处理,最终实现异步消息的处理 使用Handler消息传递机制主要是为了多个线程并发更新UI的同时,保证线程安全 2. 相关概念解释 Handler、Message、Message Queue、Looper Android消息机制: 以Handler的sendMes

Yawn 7万+

SIWAVE仿真PCB操作说明

使用SIWAVE进行PCB仿真提取S参数的操作

sinat_15150363的博客 3069

【机器学习】机器人自动走迷宫

在本实验中,要求分别使用基础搜索算法和算法,完成机器人自动走迷宫。如上图所示,左上角的红色椭圆既是起点也是机器人的初始位置,右下角的绿色方块是出口。游戏规则为:从起点开始,通过错综复杂的迷宫,到达目标点(出口)。在任一位置可执行动作包括:向上走'u'、向右走'r'、向下走'd'、向左走'l'。执行不同的动作后,根据不同的情况会获得不同的奖励,具体而言,有以下几种情况。需要您分别实现和的机器人,使机器人自动走到迷宫的出口。

dession_Wu的博客 1939

Qt Installer Framework 简单使用

qt installer framework 简单使用

qq_42815643的博客 2576

python项目分享 python走迷宫小游戏

🔥 Hi,各位同学好呀,这里是L学长!🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品python小游戏毕设 走迷宫小游戏设计与实现 (源码)🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分)难度系数:3分工作量:3分创新点:4分简介Pygame是一系列专门为编写电子游戏而设计的Python模块(modules)。Pygame在已经非常优秀的SDL库的基础上增加了许多功能。这让你能够用Python语言编写出丰富多彩的游戏程序。

mabile123444的博客 1254

SAP Fiori Launchpad 自定义层文本翻译实战:精准修正 Tile、Catalog 与 Group 标题

SAP Fiori 项目中,入口层(tile/catalog/group)的翻译问题常被忽视,但其直接影响用户体验。与前端i18n不同,这些文本属于平台配置数据,需通过ABAP标准翻译流程(SE63)处理。关键步骤包括:使用/UI2/FLC定位Text ID和Configuration ID,根据前缀区分Main/Property WD Config Key,在SE63中锁定WDY_CONF_USERT2表对象进行翻译。操作时需注意使用系统源语言环境,翻译完成后可能需要清理缓存。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 171

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

上一篇: 选取货物 - 题解(0-1背包问题)
下一篇: 简述Unity的资源加载和内存管理
枫景Maple
博客等级 码龄2年 485粉丝 100原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值