Java 递归(完成)

Java 递归(完成),java,arrays,algorithm,recursion,Java,Arrays,Algorithm,Recursion,我写了这个应该可以工作的路径查找算法,但是我得到了大量java.lang.ArrayIndexOutOfBoundsException。该计划的目标是找到从一个点到另一个点的成本最低的最短路径。这是我的密码: public boolean travel(int[][] path, int cX, int cY, int eX, int eY) { boolean returned = false; System.out.println("the current X positio

我写了这个应该可以工作的路径查找算法,但是我得到了大量java.lang.ArrayIndexOutOfBoundsException。该计划的目标是找到从一个点到另一个点的成本最低的最短路径。这是我的密码:

public boolean travel(int[][] path, int cX, int cY, int eX, int eY)
{
    boolean returned = false;
    System.out.println("the current X position on the GRID is: "+cX+"the current y position on the GRID is: "+cY);
    path[cX][cY]=1;
    if(cost>lowestCost - grid[cX][cY]){ 
        return false;
    }
    cost += grid[cX][cY];
    if(cX>=eX && cY>=eY){
        return true;
    }
    if(cX+1>=eX && cY+1<eY){
        return false;
    }
    if(cY+1>=eY && cX+1<eX){
        return false;
    }
    if(travel(path,cX+1,cY+1,eX,eY)==true){
        returned=true;
        replace(newBest, path);
    }
    if(travel(path,cX,cY+1,eX,eY)==true){
        returned=true;
        replace(newBest, path);
    }
    if(travel(path,cX+1,cY,eX,eY)==true){
        returned=true;
        replace(newBest, path);
    }


    return(returned);

}
这就是我如何调用该方法来查找最短路径

这是整个小程序:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class GridWorld extends Applet implements Runnable, MouseListener, KeyListener,     MouseMotionListener
{
public int worldx;
public int worldy;
public int columns;
public int rows;
public int destX, destY;
public int cost, lowestCost;
public boolean sizeD;
public int[][] grid;

public int[][] prevBest;

public int[][] newBest;


Graphics bufferGraphics; //Set up double buffer
Image offscreen;
Thread thread;//Sets up a Thread called thread

public void init()
{
    worldx=1000;
    worldy=1000;
    cost=0;
    lowestCost=5000;
    sizeD=false;
    columns=5;
    rows=5;
    destX=0;
    destY=0;
    grid= new int[rows][columns];
    prevBest= new int[rows][columns];
    newBest = new int[rows][columns];



    offscreen = createImage(worldx,worldy); //create a new image that's the size of the applet DOUBLE BUFFER SET UP
    bufferGraphics = offscreen.getGraphics(); //set bufferGraphics to the graphics of the offscreen image. DOUBLE BUFFER SET UP

    addKeyListener(this);//setup all the listeners
    addMouseListener(this);//setup all the listeners
    addMouseMotionListener(this);//setup all the listeners
    thread = new Thread(this);  //constructs a new thread
    thread.start();             //starts the thread
}//init()
public void fillGrid()
{
    prevBest= new int[rows][columns];
    newBest = new int[rows][columns];
    lowestCost = 0;
    for(int ro = 0;ro<rows;ro++)
    {
        for(int col = 0;col<columns;col++)
        {
                grid[ro][col]=(int)(Math.random()*100);
                newBest[ro][col]=0;
                prevBest[ro][col]=0;
                if(ro==col)
                {
                    prevBest[ro][col]=1;
                    lowestCost+=grid[ro][col];


                }
        }
    }

    destX=(rows-1);
    destY=(columns-1);
}
public boolean baseCase(int ct, int lowct, int destR, int destC, int cX, int cY)
{
    boolean returned=false;
    if(ct>=lowct)
    {
        returned=true;
    }
    if(cX+1==rows)
    {
        returned=true;
    }
    if(cY+1==columns)
    {
        returned=true;
    }
    if(cX==destR && cY==destC)
    {
        returned=true;
    }

    return(returned);
}
public boolean isValid(int x, int y, int[][] path, int eX, int eY) {
    //not valid if: cordinates are into grid dimensions
   if (!((x >= 0 && x < grid.length) && (y >= 0 && y < grid.length)))
       return false;
   //valid if: not visited yet, or is destiny
   if (path[x][y] == 0 || (x == eX && y == eY))
       return true;

   return true;
}
/*public int traverse(int steps, int destR, int destC, int curX, int curY)
{
    int direction = 0;
    if(cost>=lowestCost)
    {
        //System.out.println("Greater cost Base Case");
        direction=4;
    }
    if(curX+1>=destR && curY+1<destC)
    {
        System.out.println("Reached the farthest row Base Case");
        direction=1;
    }
    if(curY+1>=destC && curY+1<destR)
    {
        System.out.println("Reached the farthest columns Base Case");
        direction=2;
    }
    if(curX+1>=destR && curY+1>=destC)
    {
        System.out.println("At destination Base Case");
        direction=4;    
    }
    switch(direction)
    {
        case 0: newBest[curX][curY]=1;
                cost+=grid[curX][curY];
                System.out.println("the current X position on the GRID is: "+curX+"the current y position on the GRID is: "+curY);
                return(traverse(steps+1,destR,destC,curX+1,curY+1)); //diag

        case 1: newBest[curX][curY]=1;
                cost+=grid[curX][curY];
                return(traverse(steps+1,destR,destC,curX,curY+1)); //right

        case 2: newBest[curX][curY]=1;
                cost+=grid[curX][curY];
                return(traverse(steps+1,destR,destC,curX+1,curY));//down

        case 3: 
                return(5000);

        case 4: System.out.println("the Grid's cost is: "+cost);
                return(cost);
        default: return(0);

    }
}*/

 public int[][] replace(int[][] p1, int[][] p2)
 {
    for(int col=0;col<columns;col++)
        {
            for(int ro=0;ro<rows;ro++)
            {
                p1[ro][col]=p2[ro][col];
            }
        }
    return(p1);
 }
public boolean travel(int[][] path, int cX, int cY, int eX, int eY)
{
    boolean returned = false;
    System.out.println("cX: "+ cX+" , cY: "+ cY+", eX: "+eX+", eY: " +eY+" Path 1 length: "+path[0].length+" Path 2 length: "+path[1].length);
    path[cX][cY]=1;
    if(cost>lowestCost - grid[cX][cY]){ 
        System.out.println("1");
        return false;
    }
    cost += grid[cX][cY];

    }
    if(travel(path,cX+1,cY+1,eX,eY)==true && isValid(cX+1,cY+1,newBest,eX,eY)){
        System.out.println("the current X position on the GRID is: "+cX+"the current y position on the GRID is: "+cY);
        returned=true;
        replace(newBest, path);
    }
    if(travel(path,cX,cY+1,eX,eY)==true && isValid(cX,cY+1,newBest,eX,eY)){
        System.out.println("the current X position on the GRID is: "+cX+"the current y position on the GRID is: "+cY);

        returned=true;
        replace(newBest, path);
    }
    if(travel(path,cX+1,cY,eX,eY)==true && isValid(cX+1,cY,newBest,eX,eY)){
        System.out.println("the current X position on the GRID is: "+cX+"the current y position on the GRID is: "+cY);

        returned=true;
        replace(newBest, path);
    }


    return(returned);

}

public void paint(Graphics g) 
{// paint() is used to display things on the screen
    setSize(worldx,worldy);
    //clear the offscreen image
    bufferGraphics.clearRect(0,0,worldx,worldy);
    bufferGraphics.setColor(Color.black);
    //bufferGraphics.fillRect(0,0,worldx,worldy);

    if(sizeD==true)
    {
        if(travel(newBest,0,0,rows,columns)==true)
                {
                    lowestCost=cost;
                }
    }
    for(int ro = 0;ro<rows;ro++)
    {
        for(int col = 0;col<columns;col++)
        {
            if(sizeD==true)
            {

                if(newBest[ro][col]==1)
                {
                    bufferGraphics.setColor(Color.red);
                    bufferGraphics.fillRect((50*col),(50*ro),50,50);
                    bufferGraphics.setColor(Color.black);
                }
                if(prevBest[ro][col]==1)
                {
                    bufferGraphics.setColor(Color.gray);
                    bufferGraphics.fillRect((50*col),(50*ro),50,50);
                    bufferGraphics.setColor(Color.black);
                }

                bufferGraphics.drawLine(0,(50*ro),50*columns,(50*ro));
                bufferGraphics.drawLine((50*col),0,(50*col),50*rows);
                bufferGraphics.drawString(""+grid[ro][col],(50*ro)+25,(50*col)+25);



            }

        }
    }

    if(sizeD==false)
    {
        bufferGraphics.drawRect(200,300,100,100);
        bufferGraphics.drawString("5",250,350);
        bufferGraphics.drawRect(400,300,100,100);
        bufferGraphics.drawString("10",450,350);
        bufferGraphics.drawRect(600,300,100,100);
        bufferGraphics.drawString("20",650,350);
    }


    g.drawImage(offscreen,0,0,worldx,worldy,this);//Draw the screen
}// paint()

public void mouseDragged(MouseEvent e) {

}
public void mouseMoved(MouseEvent e){

}
public void mousePressed(MouseEvent e) 
{

}
public void mouseReleased(MouseEvent e) 
{

}
public void mouseEntered(MouseEvent e) 
{
   System.out.println("Mouse entered");
}
public void mouseExited(MouseEvent e) 
{
   System.out.println("Mouse exited");
}
public void mouseClicked(MouseEvent e) 
{
   System.out.println("Mouse clicked (# of clicks: "+ e.getClickCount() + ")");
   int mX=e.getX();
   int mY=e.getY();
   if(new Rectangle(200,300,100,100).contains(mX,mY) && sizeD==false)
   {
    columns=5;
    rows=5;
    grid= new int[rows][columns];
    fillGrid();
    sizeD=true;
   }
   if(new Rectangle(400,300,100,100).contains(mX,mY) && sizeD==false)
   {
    columns=10;
    rows=10;
    grid= new int[rows][columns];
    fillGrid();
    sizeD=true;

   }
   if(new Rectangle(600,300,100,100).contains(mX,mY) && sizeD==false)
   {
    columns=20;
    rows=20;
    grid= new int[rows][columns];
    fillGrid();
    sizeD=true;
   }

}
public void keyPressed( KeyEvent event ) 
{
    String keyin; // define a non‐public variable to hold the string representing the key input
    keyin = ""+event.getKeyText( event.getKeyCode()); 
    System.out.println("Key pressed "+keyin);
}//keyPressed()
public void keyReleased( KeyEvent event ) 
{
    String keyin;
    keyin = ""+event.getKeyText( event.getKeyCode()); 
    System.out.println ("Key released: "+ keyin);
}//keyReleased()
public void keyTyped( KeyEvent event ) 
{
 char keyin;
keyin = event.getKeyChar(); //getKeyChar() returns the character of the printable key pressed. 
System.out.println ("Key Typed: "+ keyin);
}//keyTyped()
public void update (Graphics g) 
{
    paint(g); 
}//Update the graphics

public void run() 
{
    while(true) // this thread loop forever and runs the paint method and then sleeps.
    {

        repaint();
        try {
        thread.sleep(50);
        }
        catch (Exception e){ }
    }//while
}// run()
import java.applet.*;
导入java.awt.*;
导入java.awt.event.*;
导入java.util.*;
公共类GridWorld扩展小程序实现Runnable、MouseListener、KeyListener、MouseMotionListener
{
公共int worldx;
公众与世俗;
公共int列;
公共int行;
公共int destX,destY;
公共int成本,最低成本;
公共图书馆;
公共int[][]网格;
公共int[]prevBest;
公共int[]newBest;
Graphics bufferGraphics;//设置双缓冲区
屏幕外图像;
Thread Thread;//设置一个名为Thread的线程
公共void init()
{
worldx=1000;
世俗的=1000;
成本=0;
最低成本=5000;
大小=假;
列=5;
行数=5;
destX=0;
destY=0;
网格=新的整数[行][列];
prevBest=新整型[行][列];
newBest=新的int[行][列];
offscreen=createImage(worldx,worldy);//创建一个与小程序双缓冲区设置大小相同的新图像
bufferGraphics=offscreen.getGraphics();//将bufferGraphics设置为offscreen图像的图形。双缓冲区设置
addKeyListener(this);//设置所有侦听器
addMouseListener(this);//设置所有侦听器
addMouseMotionListener(this);//设置所有侦听器
thread=newthread(this);//构造一个新线程
thread.start();//启动线程
}//init()
公共空间填充网格()
{
prevBest=新整型[行][列];
newBest=新的int[行][列];
最低成本=0;
对于(int ro=0;ro=0&&x=0&&y=最低成本)
{
//System.out.println(“更高成本基本情况”);
方向=4;
}
如果(curX+1>=dest&&curY+1=destC&&curY+1=dest&&curY+1>=destC)
{
System.out.println(“在目标基本情况下”);
方向=4;
}
开关(方向)
{
案例0:newBest[curX][curY]=1;
成本+=电网[curX][curY];
System.out.println(“网格上的当前X位置为:“+curX+”,网格上的当前y位置为:“+curY”);
返回(遍历(步数+1,desr,destC,curX+1,curY+1));//诊断
案例1:newBest[curX][curY]=1;
成本+=电网[curX][curY];
返回(遍历(步骤+1、desr、destC、curX、curY+1));//右
案例2:newBest[curX][curY]=1;
成本+=电网[curX][curY];
返回(遍历(步数+1,desr,destC,curX+1,curY));//向下
案例3:
返回(5000);
案例4:System.out.println(“网格的成本为:“+成本”);
收益(成本);
默认值:返回(0);
}
}*/
公共int[][]替换(int[]]p1,int[]]p2)
{

对于(int col=0;col这可能不是主题,但您是否尝试在Java中实现Dijkstra的算法。在以下算法中,代码u:=Q中的顶点,最小距离[u],在顶点集中搜索具有最小距离[u]值的顶点u。长度(u,v)返回边连接的长度(即之间的距离)两个相邻节点u和v。第17行上的变量alt是从根节点到相邻节点v的路径长度(如果要通过u)。如果该路径比为v记录的当前最短路径短,则当前路径将替换为该alt路径。前一个数组将填充指向“下一跳”的指针在源图上的节点以获得到源的最短路径。(摘自维基百科关于Dijkstra算法的文章。这不是我自己的工作。)

function Dijkstra(Graph, source):
  dist[source]  := 0                     // Distance from source to source
  for each vertex v in Graph:            // Initializations
      if v ≠ source
          dist[v]  := infinity           // Unknown distance function from source to v
          previous[v]  := undefined      // Previous node in optimal path from source
      end if 
      add v to Q                         // All nodes initially in Q (unvisited nodes)
  end for

  while Q is not empty:                  // The main loop
      u := vertex in Q with min dist[u]  // Source node in first case
      remove u from Q 

      for each neighbor v of u:           // where v has not yet been removed from Q.
          alt := dist[u] + length(u, v)
          if alt < dist[v]:               // A shorter path to v has been found
              dist[v]  := alt 
              previous[v]  := u 
          end if
      end for
  end while
  return dist[], previous[]
 end function
函数Dijkstra(图,源):
距离[源]:=0//源到源的距离
对于Graph://初始化中的每个顶点v
如果v≠ 来源
距离[v]:=无穷大//从源到v的未知距离函数
previous[v]:=未定义//源的最佳路径中的上一个节点
如果结束
将v添加到Q//最初在Q中的所有节点(未访问的节点)
结束
而Q不是空的://主循环
u:=Q中具有最小距离[u]//第一种情况下的源节点的顶点
从Q中删除u
对于u://的每个相邻v,其中v尚未从Q中移除。
高度:=距离[u]+长度(u,v)
如果alt
您将获得大量的
java.lang.ArrayIndexOutOfBoundsException
,因为您没有正确管理流以进入最后三个if块。代码将进入最后三个if块,因为您只返回
返回(returned)时的状态;
即使您设置了边界检查(前两个if块)。因此,
路径[cX][cY]
网格[cX][cY]
在cX和cY为大值时可能会遇到索引越界(取决于路径和网格的索引设置)

此外,前四个if块的检查逻辑顺序不正确,当条件满足时,您应该返回状态

前四个if块应重新排列为:

if(cost>=lowestCost){ 
    return false;
}
if(cX==eX && cY==eY){
    return true;
}
if(cX+1>=eX && cY+1<eY){
    return false;
}
if(cY+1>=eY && cX+1<eX){
    return false;
}

这是一个带回溯的递归解决方案,代码解释如下:

public class FindShortestPath {

    //the map is represented as a graph, and the graph is represented as an adyacent matrix
    int map[][] = {{-1, 1, 1, 20},    //-1 = there is no edge between two vertexs
                  {-1, -1, 3, 1},
                  {-1, -1, -1, 1},
                  {-1, -1, -1, -1}};
    
    int distSol = Integer.MAX_VALUE;                    //we want to minimize this value
    List<Integer> solution = new ArrayList<Integer>();  //path solution

    public static void main(String[] args) {
        new FindShortestPath().start();
    }

    void start() {
        /* In this case we find shortest path from 0 to 3 */
        findShortestPath(new boolean[map.length], 0, 3, 0, new ArrayList<Integer>());
        
        System.out.println("Distance: " + distSol);
        System.out.println(solution.toString());
    }

    /**
     * 
     * @param visit   auxiliary array to mark visited
     * @param c       actual vertex
     * @param destiny destiny vertex
     * @param distAct actual distance traveled
     * @param path    actual path traveled
     */
    void findShortestPath(boolean visit[], int c, int destiny, int distAct, List<Integer> path) {
        if (c == destiny) {                             //base case: we reach destiny
            if (distAct <= distSol) {                   //check if actual distance is better than solution                
                distSol = distAct;
                solution = new ArrayList<Integer>(path);   //replace old solution
                solution.add(destiny);
            }
        } else {                                        //recursive case
            path.add(c);                                //add actual vertex as a possible candidate into actual path
            visit[c] = true;

            for (int i = 0; i < map.length; i++) {      //visit every adyacent vertex that was no visited yet
                if (map[c][i] != -1 && !visit[i]) {
                    findShortestPath(visit, i, destiny, distAct + map[c][i], path);
                }
            }

            path.remove(path.size() - 1);               //remove this vertex from the path
            visit[c] = false;
        }
    }
}

谢谢hkg279,它解决了很多问题,但我仍然在代码中遇到更多问题,现在只有一个例外
if(cost>lowestCost - grid[cX][cY]){ 
    return false;
}
cost += grid[cX][cY];
public class FindShortestPath {

    //the map is represented as a graph, and the graph is represented as an adyacent matrix
    int map[][] = {{-1, 1, 1, 20},    //-1 = there is no edge between two vertexs
                  {-1, -1, 3, 1},
                  {-1, -1, -1, 1},
                  {-1, -1, -1, -1}};
    
    int distSol = Integer.MAX_VALUE;                    //we want to minimize this value
    List<Integer> solution = new ArrayList<Integer>();  //path solution

    public static void main(String[] args) {
        new FindShortestPath().start();
    }

    void start() {
        /* In this case we find shortest path from 0 to 3 */
        findShortestPath(new boolean[map.length], 0, 3, 0, new ArrayList<Integer>());
        
        System.out.println("Distance: " + distSol);
        System.out.println(solution.toString());
    }

    /**
     * 
     * @param visit   auxiliary array to mark visited
     * @param c       actual vertex
     * @param destiny destiny vertex
     * @param distAct actual distance traveled
     * @param path    actual path traveled
     */
    void findShortestPath(boolean visit[], int c, int destiny, int distAct, List<Integer> path) {
        if (c == destiny) {                             //base case: we reach destiny
            if (distAct <= distSol) {                   //check if actual distance is better than solution                
                distSol = distAct;
                solution = new ArrayList<Integer>(path);   //replace old solution
                solution.add(destiny);
            }
        } else {                                        //recursive case
            path.add(c);                                //add actual vertex as a possible candidate into actual path
            visit[c] = true;

            for (int i = 0; i < map.length; i++) {      //visit every adyacent vertex that was no visited yet
                if (map[c][i] != -1 && !visit[i]) {
                    findShortestPath(visit, i, destiny, distAct + map[c][i], path);
                }
            }

            path.remove(path.size() - 1);               //remove this vertex from the path
            visit[c] = false;
        }
    }
}
public class FindShortestPath2 {

    int lowestCost = Integer.MAX_VALUE;
    
    int grid[][] = {{0, 9, 0, 0},  
                   { 0, 5, 1, 1},
                   { 0, 0, 2, 0},
                   { 0, 0, 0, 0}};
    
    int sol[][] = new int[4][4];      //this is the path solution
    
    public static void main(String[] args) {
        new FindShortestPath2().start();
    }

    void start() {
        travel(new int[4][4], 0, 0, 2, 2, 0);
        System.out.println("Lowest cost: " + lowestCost);
        printPath(sol);  //print solution
    }

    public void travel(int[][] path, int cX, int cY, int eX, int eY, int cost) {
        if (cX == eX && cY == eY) {    //reach destiny cordinates
            if (cost < lowestCost) {
                lowestCost = cost;
                path[cX][cY] = 1;
                replace(sol, path);             
            }
        } else {
            path[cX][cY] = 1;         //mark path
            
            if (isValid(cX + 1, cY + 1, path, eX, eY)) {    //move in diagonal (rigth-down)       
                travel(path, cX + 1, cY + 1, eX, eY, cost + grid[cX + 1][cY+1]);
            }
            if (isValid(cX, cY + 1, path, eX, eY)) {        //move rigth
                travel(path, cX, cY + 1, eX, eY, cost + grid[cX][cY+1]);
            }
            if (isValid(cX + 1, cY, path, eX, eY)) {        //move down
                travel(path, cX + 1, cY, eX, eY, cost + grid[cX + 1][cY]);
            }

            path[cX][cY] = 0;       //unmark path
        }
    }

    
    boolean isValid(int x, int y, int[][] path, int eX, int eY) {
        //not valid if: cordinates are into grid dimensions
       if (!((x >= 0 && x < grid.length) && (y >= 0 && y < grid.length)))
           return false;
       
       //valid if: not visited yet, or is destiny
       if (path[x][y] == 0 || (x == eX && y == eY))
           return true;
       
       return true;
    }
    
    void replace(int[][] p1, int[][] p2) {
        for (int col = 0; col < p1.length; col++) {
            for (int ro = 0; ro < p1.length; ro++) {
                p1[ro][col] = p2[ro][col];
            }
        }
    }
    
    void printPath(int[][] p) {
        for (int col = 0; col < p.length; col++) {
            for (int ro = 0; ro < p.length; ro++) {
                System.out.print(p[col][ro] + " ");
            }
            System.out.println();
        }
        System.out.println();
    }
}
Lowest cost: 2

1 0 0 0 
1 0 0 0 
0 1 1 0 
0 0 0 0