迷宫中鼠的最短路径,可选择移除一面墙

时间:2016-12-20 04:51:43

标签: java matrix multidimensional-array queue dynamic-programming

这是问题所在: 你有空间站部分地图,每个地图都从一个监狱出口开始,一直到逃生舱的门口。地图表示为0和1的矩阵,其中0是可通行空间,1是无法通过的墙。从监狱出来的门位于左上方(0,0),进入逃生舱的门位于右下方(w-1,h-1)。

写一个函数答案(地图),生成从监狱门到逃生舱的最短路径的长度,在那里你可以拆除一面墙作为重建计划的一部分。路径长度是您通过的节点总数,计算入口和出口节点。起始位置和结束位置始终可以通过(0)。虽然您可能需要也可能不需要拆除墙壁,但地图始终可以解决。地图的高度和宽度可以是2到20.移动只能在基本方向上进行;不允许对角线移动。

总结问题:这是一个迷宫问题的简单老鼠,大鼠从基质中的(0,0)开始,应达到(w-1,h-1)。迷宫是一个0和1的矩阵。 0表示路径,1表示墙。您可以移除一面墙(将其从0更改为1)。找到最短的路径。

我已经解决了这个问题,但是5个测试用例中有3个失败了,我不知道那些测试用例是什么。而且我无法弄清楚原因。任何帮助将不胜感激。谢谢你提前。这是我的代码:

import java.util.*;

class Maze{//Each cell in matrix will be this object
Maze(int i,int j){
    this.flag=false;
    this.distance=0;
    this.x=i;
    this.y=j;
}
boolean flag;
int distance;
int x;
int y;
}

class Google4_v2{
public static boolean isPresent(int x,int y,int r,int c)
{
    if((x>=0&&x<r)&&(y>=0&&y<c))
        return true;
    else
        return false;
}
public static int solveMaze(int[][] m,int x,int y,int loop)
{
    int r=m.length;
    int c=m[0].length;
    int result=r*c;
    int min=r*c;
    Maze[][] maze=new Maze[r][c];//Array of objects
    for(int i=0;i<r;i++)
    {
        for(int j=0;j<c;j++)
        {
            maze[i][j]=new Maze(i,j);
        }
    }
    Queue<Maze> q=new LinkedList<Maze>();

    Maze start=maze[x][y];
    Maze[][] spare=new Maze[r][c];
    q.add(start);//Adding source to queue
    int i=start.x,j=start.y;
    while(!q.isEmpty())
    {
        Maze temp=q.remove();
        i=temp.x;j=temp.y;
        int d=temp.distance;//distance of a cell from source 
        if(i==r-1 &&j==c-1)
        {
            result=maze[i][j].distance+1;
            break;
        }
        maze[i][j].flag=true;
        if(isPresent(i+1,j,r,c)&&maze[i+1][j].flag!=true)//check down of current cell
        {
            if(m[i+1][j]==0)//if there is path, add it to queue
            {
            maze[i+1][j].distance+=1+d;
            q.add(maze[i+1][j]);
            }
            if(m[i+1][j]==1 && maze[i+1][j].flag==false && loop==0)//if there is no path, see if breaking the wall gives a path.
            {
             int test=solveMaze(m,i+1,j,1);
             if(test>0)
             {
                test+=d+1;
                min=(test<min)?test:min;
             }
             maze[i+1][j].flag=true;
            }
        }
        if(isPresent(i,j+1,r,c)&&maze[i][j+1].flag!=true)//check right of current cell
        {
            if(m[i][j+1]==0)
            {
            maze[i][j+1].distance+=1+d;
            q.add(maze[i][j+1]);
            }
            if(m[i][j+1]==1 && maze[i][j+1].flag==false && loop==0)
            {
             int test=solveMaze(m,i,j+1,1);
             if(test>0)
             {
                test+=d+1;
                min=(test<min)?test:min;
             }
             maze[i][j+1].flag=true;
            }
        }
        if(isPresent(i-1,j,r,c)&&maze[i-1][j].flag!=true)//check up of current cell
        {
            if(m[i-1][j]==0)
            {
            maze[i-1][j].distance+=1+d;
            q.add(maze[i-1][j]);
            }
            if(m[i-1][j]==1 && maze[i-1][j].flag==false && loop==0)
            {
             int test=solveMaze(m,i-1,j,1);
             if(test>0)
             {
                test+=d+1;
                min=(test<min)?test:min;
             }
             maze[i-1][j].flag=true;
            }
        }
        if(isPresent(i,j-1,r,c)&&maze[i][j-1].flag!=true)//check left of current cell
        {
            if(m[i][j-1]==0)
            {
            maze[i][j-1].distance+=1+d;
            q.add(maze[i][j-1]);
            }
            if(m[i][j-1]==1 && maze[i][j-1].flag==false && loop==0)
            {
             int test=solveMaze(m,i,j-1,1);
             if(test>0)
             {
                test+=d+1;
                min=(test<min)?test:min;
             }
             maze[i][j-1].flag=true;
            }
        }
    }
    return ((result<min)?result:min);

}
public static int answer(int[][] m)
{
    int count;
    int r=m.length;
    int c=m[0].length;
    count=solveMaze(m,0,0,0);
    return count;
}
public static void main(String[] args)
{
    Scanner sc=new Scanner(System.in);
    System.out.println("enter row size ");
    int m=sc.nextInt();
    System.out.println("enter column size ");
    int n=sc.nextInt();
    int[][] maze=new int[m][n];
    System.out.println("Please enter values for maze");
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            maze[i][j]=sc.nextInt();
        }
    }
    int d=answer(maze);
    System.out.println("The maze can be solved in "+d+" steps");
}

}

2 个答案:

答案 0 :(得分:1)

发现问题。在maze[i][j].flag=true;条件内访问单元格时,需要立即放置if(m[i+1][j]==0)。否则,可以通过多个单元格添加相同单元格的距离

答案 1 :(得分:0)

不幸的是,很难帮助你,因为你的代码很难阅读。变量通常是单个字符,这使得无法知道它们应该代表什么。调试它比我们大多数人愿意给予的帮助更多: - )

我建议您按如下方式调试代码:

  1. solveMaze方法拆分为多个较小的方法,每个方法执行更简单的功能。例如,对于每个方向,您有非常相似的代码重复4次。努力将该代码放在一个可以调用4次的方法中。移动代码以将数组创建为新方法。基本上每种方法都应该做一件简单的事情。这种方法可以在出现问题时更容易找到问题。

  2. 编写单元测试以确保在尝试计算整个迷宫的答案之前,每个方法都完全符合您的预期。

  3. 一旦所有方法都正常工作,就会生成一些迷宫,从非常简单的情况开始到非常复杂的情况。

  4. 如果案例失败,请使用交互式调试程序遍历您的代码,看看它出错的地方。

  5. 祝你好运。