Java 递归(完成)
我写了这个应该可以工作的路径查找算法,但是我得到了大量java.lang.ArrayIndexOutOfBoundsException。该计划的目标是找到从一个点到另一个点的成本最低的最短路径。这是我的密码: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
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