min steps and path

本文介绍了一种使用广度优先搜索(BFS)算法来寻找二维数组中从起点到终点的最短路径的方法,并提供了具体的Java实现代码。该算法适用于路径上无障碍(标记为1)的情况。

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

给一个board,上面有0 和1,1不可以走,0 可以走。任意给一个start一个end,让输出最短的步数。follow up输出路径。就是BFS

public int minsteps(int board[][], int starti, int startj, int endi, int endj) {
        int dirs[][] = new int[][] { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
        int m = board.length;
        int n = board[0].length;

        boolean visited[][] = new boolean[m][n];
        Queue<int[]> queue = new LinkedList<>(); // bfs

        queue.offer(new int[] { starti, startj });
        visited[starti][startj] = true;

        int level = 0;
        while (!queue.isEmpty()) {
            level++;
            int count = queue.size();
            for (int i = 0; i < count; i++) {
                int[] node = queue.poll();
                for (int[] dir : dirs) {
                    //决定四个方向
                    int x = node[0] + dir[0];
                    int y = node[1] + dir[1];
                    if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != 1 && !visited[x][y]) {
                        if (x == endi && y == endj) {
                            return level;
                        }
                        queue.offer(new int[] { x, y });
                        visited[x][y] = true;
                    }
                }
            }
        }
        return -1;
    }

    public List<int[]> minpath(int board[][], int starti, int startj, int endi, int endj) {
        int dirs[][] = new int[][] { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
        int m = board.length;
        int n = board[0].length;

        Map<Integer, Integer> parent = new HashMap<>(); // int[] cannot equals
        boolean visited[][] = new boolean[m][n];
        Queue<int[]> queue = new LinkedList<>(); // bfs

        queue.offer(new int[] { starti, startj });
        visited[starti][startj] = true;

        while (!queue.isEmpty()) {
            int count = queue.size();
            for (int i = 0; i < count; i++) {
                int[] node = queue.poll();
                for (int[] dir : dirs) {
                    int x = node[0] + dir[0];
                    int y = node[1] + dir[1];
                    if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] != 1 && !visited[x][y]) {
                        queue.offer(new int[] { x, y });
                        visited[x][y] = true;
                        //编码,保存
                        parent.put(x * n + y, node[0] * n + node[1]);
                        if (x == endi && y == endj) {
                            LinkedList<int[]> ret = new LinkedList<>();
                            while (x * n + y != starti * n + startj) {
                                ret.offerFirst(new int[] { x, y });
                                int p = parent.get(x * n + y);
                                x = p / n;
                                y = p % n;
                            }
                            return ret;
                        }
                    }
                }
            }
        }
        return null;
    }

    public static void main(String[] args) {
        MinPath s = new MinPath();
        System.out.println(s.minsteps(new int[][] { { 0, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 } }, 0, 1,
                1, 1));
        System.out.println(s.minsteps(new int[][] { { 0, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 } }, 0, 1,
                2, 1));
        System.out.println(s.minsteps(new int[][] { { 0, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 } }, 0, 1,
                2, 2));
        System.out.println();

        System.out.println(s.minpath(new int[][] { { 0, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 } }, 0, 1,
                1, 1));
        for (int[] t : s.minpath(new int[][] { { 0, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 } }, 0, 1, 2, 1))
            System.out.print("(" + t[0] + "," + t[1] + ") ");
        System.out.println();
        for (int[] t : s.minpath(new int[][] { { 0, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 } }, 0, 1, 2, 2))
            System.out.print("(" + t[0] + "," + t[1] + ") ");
        System.out.println();
    }


globals [ evacuation_time ; 总疏散时间(秒) total_students ; 学生总数 exited_students ; 已疏散学生数 evacuation_data ; 存储疏散率数据 available_chairs ; 椅子总数 stop-requested? ; 停止实验标志 ] patches-own [ is_obstacle? ; 是否为障碍物 is_exit? ; 是否为出口 exit_id ; 出口编号(1或2) is_chair? ; 是否为椅子 ] turtles-own [ target_exit ; 目标出口 moved? ; 本回合是否已移动 speed ; 当前移动速度 consecutive_failures ; 连续移动失败次数 ] ; 初始化设置 to setup clear-all set evacuation_data [] set exited_students 0 set evacuation_time 0 set total_students num_students set stop-requested? false ; 重置停止标志 setup-classroom set available_chairs find-available-chairs ; 获取可用椅子位置 create-students reset-ticks end ; 查找所有可用椅子位置 to-report find-available-chairs report sort patches with [is_chair?] ; 返回所有椅子地块 end ; 设置教室布局 to setup-classroom ; 教室尺寸:26x24 patches (13m x 12m, 0.5m/格) ask patches [ set pcolor white ; 默认地板 set is_obstacle? false set is_exit? false set is_chair? false ] ; 设置讲台区域 (前部中央) ask patches with [pxcor >= 10 and pxcor <= 15 and pycor >= 23 and pycor <= 25] [ set pcolor blue set is_obstacle? true set is_chair? false ] ; 设置桌椅布局 (A/B/C三区) setup-seats "A" 3 5 1 3 ; A区:3列5排 setup-seats "B" 4 5 9 3 ; B区:4列5排 setup-seats "C" 3 4 19 7 ; C区:3列4排 ; 设置过道 (1m宽) ask patches with [ (pxcor >= 7 and pxcor <= 8 and pycor <= 20) or ; AB区域间过道 (pxcor >= 17 and pxcor <= 18 and pycor <= 20) or ; BC区域间过道 (pycor >= 21 and pycor <= 22) ; 前排过道 ] [ set pcolor yellow set is_chair? false ] let select_type exit_type ; 设置出口 ask patches with [pxcor >= 23 and pxcor <= 24 and pycor >= 24 and pycor <= 25] [ ; 出口0 set pcolor green set is_exit? true set is_chair? false set exit_id 0 ] If select_type = “double” [ ask patches with [pxcor >= 23 and pxcor <= 24 and pycor >= 2 and pycor <= 3][ ; 出口1 set pcolor green set is_exit? true set is_chair? false set exit_id 1 ] ] ; 设置墙壁 ask patches [ if (pxcor = 0 or pxcor = 25 or pycor = 0 or pycor = 27) and not (pycor = 24 and (pxcor = 12 or pxcor = 14)) [ set pcolor gray set is_obstacle? true set is_chair? false ] ] end ; 设置座位区域 to setup-seats [region cols rows start_x start_y] let j 0 while [j < rows] [ let x start_x ; 列间隔2格(1米) let y start_y + j * 4 ; 行间隔2格(1米) ; 设置桌子 ask patches with [pxcor >= x and pxcor < 2 * cols + x and pycor >= y and pycor <= y + 1] [ set pcolor black set is_obstacle? true set is_chair? false ] ; newcode-chair let i 0 while [i < cols][ let chair_x start_x + i * 2 let chair_y y - 2 ask patch chair_x chair_y[ set pcolor gray + 1 set is_chair? true ] set i i + 1 ] set j j + 1 ] end ; 创建学生(修改后) to create-students ; 检查椅子数量是否足够 if total_students > length available_chairs [ user-message (word "需要 " total_students " 个座位,但只有 " count available_chairs " 个座位可用。") stop ] create-turtles total_students [ set color blue set shape "person" set size 2 set speed 1.2 set moved? false set target_exit -1 set consecutive_failures 0 ; 初始化连续失败次数 ; 随机选择一个椅子位置 let chair one-of available_chairs set available_chairs remove chair available_chairs ; 从可用列表中移除 ; 移动到椅子位置 if chair != nobody [ ; 获取椅子地块的坐标 let chair-x [pxcor] of chair let chair-y [pycor] of chair ; 计算学生位置(椅子中心偏下) let student-x chair-x ; 椅子区域中心x let student-y chair-y + 0.5 ; 下移0.25m(椅子高度的一半) ; 设置学生位置 setxy student-x student-y ] ] end ; 主循环 to go if stop-requested? [ stop ] ; 检查停止标志 ; 检查是否所有学生都已疏散 if count turtles = 0 [ set evacuation_time ticks / 10 ; 转换为秒 stop ] ask turtles [ if not moved? [ ; 本回合尚未移动 ; 到达出口检查 if [is_exit?] of patch-here [ set exited_students exited_students + 1 die ] ; 选择目标出口 if target_exit = -1 [ choose-target-exit ] ; 向出口移动 move-towards-exit set moved? true ] ] ; 记录疏散率数据 if ticks mod 10 = 0 [ ; 每10个ticks记录一次(1秒) set evacuation_data lput (list (ticks / 10) (exited_students / total_students)) evacuation_data ] ; 重置移动状态 ask turtles [ set moved? false ] tick end ; 选择目标出口 to choose-target-exit ; 双出口路径选择 let exit0 min-one-of patches with [exit_id = 0] [distance myself] let exit1 min-one-of patches with [exit_id = 1] [distance myself] let d0 [distance myself] of exit0 let d1 [distance myself] of exit1 ifelse d0 < d1 [ set target_exit 0 ] [ ifelse d0 = d1 [ set target_exit random 2 ; 距离相等时随机选择 ] [ set target_exit 1 ] ] end to move-towards-exit let nearest-exit min-one-of patches with [is_exit?] [distance myself] ; 确定最近的出口 ifelse nearest-exit != nobody [ face nearest-exit ; 检查前方补丁是否为墙壁或已被占据 let next-patch patch-ahead 1 ifelse [pcolor] of next-patch != gray and not any? other turtles-on next-patch [ move-to next-patch ] [ rt random 45 - 22.5 ; 如果前方是墙壁或被占据,则随机调整方向 ] ] [ ; 如果没有找到出口,则随机移动 rt random 360 fd 1 ] end ; 智能绕行障碍物算法 to smart-avoid-obstacle [dist] ; 尝试左右45度 if try-move-direction dist 45 [ set consecutive_failures 0 stop ] if try-move-direction dist -45 [ set consecutive_failures 0 stop ] ; 如果45度不行,尝试90度 if try-move-direction dist 90 [ set consecutive_failures 0 stop ] if try-move-direction dist -90 [ set consecutive_failures 0 stop ] ; 如果还不行,尝试135度 if try-move-direction dist 135 [ set consecutive_failures 0 stop ] if try-move-direction dist -135 [ set consecutive_failures 0 stop ] ; 最后尝试后退 if try-move-direction dist 180 [ set consecutive_failures 0 stop ] ; 如果所有方向都失败,尝试小步移动 let small-step dist / 2 if small-step > 0.05 and try-move-direction small-step random 360 [ set consecutive_failures 0 stop ] ; 增加失败计数 set consecutive_failures consecutive_failures + 1 ; 如果连续失败太多次,重新选择目标出口 if consecutive_failures > 5 [ set target_exit -1 ; 强制重新选择目标 set consecutive_failures 0 ] end ; 尝试特定方向移动 to-report try-move-direction [dist angle] let original-heading heading set heading heading + angle if my-can-move? dist [ fd dist report true ] set heading original-heading report false end ; 增强的障碍物检查 - 检查路径上的所有点 to-report my-can-move? [dist] ; 检查目标地块 let target patch-ahead dist if target = nobody [ report false ] ; 检查路径上的所有点 let steps 5 ; 检查路径上的5个点 let step-size dist / steps let current-dist step-size repeat steps [ let p patch-ahead current-dist if p != nobody and ([is_obstacle?] of p or any? other turtles-on p) [ report false ] set current-dist current-dist + step-size ] ; 检查终点 report (not [is_obstacle?] of target) and (not any? other turtles-on target) end ; 获取路径上的地块 to-report patches-along-path [angle go_distance step-size] let steps floor (go_distance / step-size) let path [] let current-x xcor let current-y ycor repeat steps [ set current-x current-x + step-size * sin angle set current-y current-y + step-size * cos angle let p patch current-x current-y if p != nobody [ set path lput p path ] ] report path end ; 运行实验 to run-experiment set stop-requested? false ; 重置停止标志 set total_students num_students setup let max-ticks 2000 ; 最大200秒 let counter 0 while [counter < max-ticks and count turtles > 0 and not stop-requested?] [ go set counter counter + 1 ; 添加短暂延迟以便界面更新 if counter mod 10 = 0 [ display ] ] ; 导出数据 export-data end ; 停止实验过程 to stop-experiment set stop-requested? true show "实验已手动停止" end ; 导出疏散数据 to export-data let filename (word "evacuation_" exit_type "_" num_students ".csv") file-open filename file-print "Time(s),EvacuationRate" foreach evacuation_data [ [data] -> file-print (word (item 0 data) "," (item 1 data)) ] file-close show word "数据已导出到: " filename end ; 获取当前疏散率 to-report evacuation-rate report exited_students / total_students end ; 可视化设置 to visualize ; 设置观察视角 resize-world -1 26 -1 25 set-patch-size 10 end我现在A 区的学生不往出口跑会卡在墙上,请帮我进行修改中If select_type = “double” [报错
最新发布
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值