[英]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 个东西。 让我们将队列中的每个项目称为一个节点。
您首先将开始 position 的计数分配给 0。
该算法的工作方式是:
在您的第 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.