繁体   English   中英

Java 中 8x8 网格的广度优先搜索

[英]Breadth-first search on an 8x8 grid in Java

我想做的是计算使用最短路径到达目标需要多少步。 它必须使用广度优先搜索来完成。 我将 8x8 网格放入一个二维数组中,其中填充了四个字符之一,E 表示空(可以移动到这些位置),B 表示阻塞(不能移动到此处),R 表示机器人(起点),或 G为目标。 该算法必须按向上、向左、向右、然后向下的顺序检查可移动空间,我相信我做对了。 检查节点后,它将其内容更改为“B”。 如果无法达到目标,则应返回 0。

我更改了我的代码以实现 Kshitij 告诉我的内容,并且效果很好。 我只是太累了,以至于看到我没有在每个新数据集之后都初始化我的队列,哈哈。 谢谢您的帮助!

public static int bfSearch(){
    Queue <int []> queue = new LinkedList <int []> ();
    int [] start = {roboty,robotx,0};
    queue.add(start);

    while (queue.peek() != null){
        int [] array = queue.remove();

            if(array[0]-1 >= 0 && grid[array[0]-1][array[1]] != 'B'){

                if (grid[array[0]-1][array[1]] == 'G'){
                    return array[2]+1; 
                }
                else{
                    grid[array[0]-1][array[1]] = 'B';
                    int [] temp = {array[0]-1, array[1], array[2]+1};
                    queue.add(temp);
                }
            }

            if(array[1]-1 >= 0 && grid[array[0]][array[1]-1] != 'B'){

                if (grid[array[0]][array[1]-1] == 'G'){
                    return array[2]+1;
                }
                else{
                    grid[array[0]][array[1]-1] = 'B';
                    int [] temp = {array[0], array[1]-1, array[2]+1};
                    queue.add(temp);
                }
            }

            if(array[1]+1 <= 7 && grid[array[0]][array[1]+1] != 'B'){

                if (grid[array[0]][array[1]+1] == 'G'){
                    return array[2]+1;
                }
                else{
                    grid[array[0]][array[1]+1] = 'B';
                    int [] temp = {array[0], array[1]+1, array[2]+1};
                    queue.add(temp);
                }
            }

            if(array[0]+1 <= 7 && grid[array[0]+1][array[1]] != 'B'){

                if (grid[array[0]+1][array[1]] == 'G'){
                    return array[2]+1;
                }
                else{
                    grid[array[0]+1][array[1]] = 'B';
                    int [] temp = {array[0]+1, array[1], array[2]+1};
                    queue.add(temp);
                }
            }
        }           
    return 0;
}

您需要在队列中存储 2 个东西。 让我们将队列中的每个项目称为一个节点。

  1. position(您已存储)
  2. 计数(从起始位置到达此 position 所需的移动)

您首先将开始 position 的计数分配给 0。

该算法的工作方式是:

  1. 你从队列中弹出一个节点
  2. 您确定您可以从刚刚弹出的节点指定的 position 到 go 的位置。 也就是说,如果您将其视为“即时制作树”,您将确定从队列中弹出的节点的子节点
  3. 您将这些孩子添加到队列中。

在您的第 3 步中,当您将一个子节点添加到队列中时,您必须确定需要添加到该节点的计数。 此计数只是count of the parent node (that you popped in step 1) + 1

最后,您的返回值将是与携带目的地 position 的节点关联的计数。

例如,让我们使用 4x4 网格,其中 position [0,0] 是起点,position [0,3] 是终点。

S E E B
E B E E
B B B E
G E E E

最初,您的队列将是:

[{(0, 0), 0}]

其中()中的值是 position, {}中的第二个值是计数。

您从队列中弹出该节点,并确定您可以到达位置 (0,1) 和 (1,0)。 因此,您将项目{(0, 1), 1}{(1, 0), 1}添加到队列中。 请注意,计数为 1,因为弹出节点的计数为 0,我们将其递增 1。您的队列现在如下所示:

[{(0, 1), 1},  {(1, 0), 1}]

你弹出第一个元素,意识到它没有可行的孩子,所以你继续前进。

您弹出剩余的元素,并发现它为您提供了一个可以到达的节点,位于 position (2, 0)。 由于您弹出的节点计数为 1,因此您将这个新的 position 与计数 = 1 + 1 = 2 配对添加到队列中。

最终,您将从队列中弹出目标节点,它的计数将为 9。

编辑

如果你想获得从源到目的地的路径,当前的编码不能按原样工作。 您需要使用计数维护一个大小为 8x8 的单独二维数组,而不是在节点本身中对它们进行编码。 当您最终找到目的地的计数时,您可以使用二维计数数组从目的地回溯到源。 本质上,如果您可以在 9 步内到达目的地,则可以在 8 步内到达其相邻位置之一。 因此,您找到计数为 8 且与目的地相邻的 position。 您反复重复此操作,直到到达源头。

您描述的向节点添加额外元素的方法不起作用。 我会留给你找出原因,因为这是家庭作业:)

这是您的代码的一个不错的简短替代方案 完全相同的想法,但不需要检查每个坐标有效性的这么多“如果”条件。 这一切都可以在一个 go 中完成。看看吧。

我已经尽可能多地评论了解释。 即使对于没有丝毫想法的人来说,它也是可读的。 当我为一个类似(相同?)的问题实施解决方案时,我碰巧遇到了你的问题,在这个问题中,一个被困在迷宫中的人必须找到出路。 网格中有陷阱(B)和可移动区域(E)。 目标是到达他的目的地(G)。

无论如何,这是通用代码。 我接受了行数、列数,然后是完整的网格。 我只打印是否有可能到达目的地。 我将 rest 留给阅读本文的人作为练习,以确保您已理解代码;)

请注意,我回答的主要目的是向您展示可以减小 BFS function 的大小 我发布我的整个解决方案只是为了给出在网格中应用 BFS 的总体思路,因为我在学习它时遇到了困难。 希望这能帮助陷入同样情况的人。 如果您想要职位或遵循的路径或其他任何内容,请按照此问题答案中的说明进行操作。 自己做;)

import java.util.*;

/**
 * Created by Shreyans on 4/30/2015 at 10:27 PM using IntelliJ IDEA
 */

class MAZE
{
    static int r,c,s1,s2,f1,f2;//Rows, Columns, Start Coordinates, Finish Coordinates
    static int[] dx={1,-1,0,0};//right, left, NA, NA
    static int[] dy={0,0,1,-1};//NA, NA, bottom, top
    static char[][] grid;//Main grid
    public static void main(String[] args)
    {
        Scanner sc=new Scanner(System.in);//I suggest using faster IO if you have performance concerns. I did. Scanner is readable hence the choice
        r=sc.nextInt();
        c=sc.nextInt();
        grid=new char[r][c];
        for(int i=0;i<r;i++)
        {
            char[] s1=sc.next().toCharArray();//Reading a line of the Grid
            System.arraycopy(s1,0,grid[i],0,c);//Nice inbuilt function to copy contents of an array. Also doable manually
        }
        s1=sc.nextInt()-1;
        s2=sc.nextInt()-1;
        f1=sc.nextInt()-1;
        f2=sc.nextInt()-1;
        if(MAZEBFS())
        {
            System.out.println("PATH EXISTS");
        }
        else
        {
            System.out.println("PATH DOES NOT EXIST");
        }
    }
    private static boolean MAZEBFS()
    {
        if(s1==f1&&s2==f2)
        {
            return true;//He's already there
        }
        else
        {
            grid [f1][f2]='G';//finish
            Queue<int[]> q=new LinkedList<int[]>();
            int[]start={s1,s2};//Start Coordinates
            q.add(start);//Adding start to the queue since we're already visiting it
            grid[s1][s2]='B';
            while(q.peek()!=null)
            {
                int[]curr=q.poll();//poll or remove. Same thing
                for(int i=0;i<4;i++)//for each direction
                {
                    if((curr[0]+dx[i]>=0&&curr[0]+dx[i]<r)&&(curr[1]+dy[i]>=0&&curr[1]+dy[i]<c))
                    {
                        //Checked if x and y are correct. ALL IN 1 GO
                        int xc=curr[0]+dx[i];//Setting current x coordinate
                        int yc=curr[1]+dy[i];//Setting current y coordinate
                        if(grid[xc][yc]=='G')//Destination found
                        {
                            //System.out.println(xc+" "+yc);
                            return true;
                        }
                        else if(grid[xc][yc]=='E')//Movable. Can't return here again so setting it to 'B' now
                        {
                            //System.out.println(xc+" "+yc);
                            grid[xc][yc]='B';//now BLOCKED
                            int[]temp={xc,yc};
                            q.add(temp);//Adding current coordinates to the queue
                        }
                    }
                }
            }
            return false;//Will return false if no route possible
        }
    }
}

行动代码: http://ideone.com/jiZKzn

欢迎提出任何建议。 干杯:D

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM