2013-11-03 3 views
0

미로에 대한 최단 경로 알고리즘을 성공적으로 완료했습니다 (아래 코드 참조). 그러나, 내 함수에 전달되는 스택 매개 변수에 최단 경로 좌표를 저장하고 싶습니다. 누군가가 이걸 어떻게 달성 할 수 있는지 조언 해 주시겠습니까?최단 경로에 대한 모든 셀 좌표를 인쇄합니다.

String[][] map = new String[][] 
    { 
      new String[] { "1","1","1","0","0","0","1","1","1","1" }, 
      new String[] { "s","0","0","0","1","1","0","0","0","1" }, 
      new String[] { "1","1","0","0","1","0","0","1","0","1" }, 
      new String[] { "1","1","1","0","0","0","0","0","0","1" }, 
      new String[] { "1","0","1","1","1","0","1","1","0","1" }, 
      new String[] { "0","0","0","0","0","0","0","0","0","1" }, 
      new String[] { "0","1","1","1","1","1","1","1","1","1" }, 
      new String[] { "0","0","0","0","0","0","0","0","0","e" }, 
    }; 

내 알고리즘 말 :

전설 : 1 : 벽, 0 : 유효한 경로, S : 시작, 전자 는 여기에 내가 작업하고있는 미로

// Pre-condition: Two integers indicating the row and col number to start from, 
// a 2d array of string objects representing the map of the maze, 
// a 2d array of booleans mapping out the visited cells in the maze 
// A string array containing the map of the maze. 
// An empty Stack object 
// Post-conditon: The distance of the shortest path from the current cell(start) 
// to the end of the maze 
public static int shortestPath(int row,int col,boolean[][] visited,String[][] map,Stack<Pair> path) 
{ 
    if(row < 0 || row >= map.length || col < 0 || col >= map[0].length) 
     return -1; 
    else if(visited[row][col] == true) 
     return -1; 
    else if(map[row][col].equals("e")) 
     return 0; 
    else 
    { 
     // Mark the current cell as visited 
     visited[row][col] = true; 

     // There is a wall 
     if(map[row][col].equals("1")) 
      return -1; 
     else 
     { 
      int[] pathDist = new int[4]; 

      // Start finding the path from the left 
      int left = 1 + shortestPath(row,col-1,visited,map,path); 

      // Start searching from the right 
      int right = 1 + shortestPath(row,col+1,visited,map,path); 

      // Start searching from the bottom 
      int down = 1 + shortestPath(row+1,col,visited,map,path); 

      // Start searching from the top 
      int up = 1 + shortestPath(row-1,col,visited,map,path); 

      visited[row][col] = false; 

      pathDist[0] = left; 
      pathDist[1] = right; 
      pathDist[2] = down; 
      pathDist[3] = up; 

      Arrays.sort(pathDist); 

      for(Integer i : pathDist) 
       if(i > 0) return i; 
      return -1; 
     } 
    } 
} 

}

답변

3

근본적으로 잘못된 접근 방식이 있습니다. 가능한 모든 경로를 미로를 통해 계산 한 다음 가장 짧은 경로를 선택하십시오. (가능한 경로의 수는 때문에, 알고리즘은 종료하지 않습니다)

String[][] map = new String[][] { 
    new String[] { "s", "0", "0", "0", "0", "0", "0", "0", "0", "0" }, 
    new String[] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" }, 
    new String[] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" }, 
    new String[] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" }, 
    new String[] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" }, 
    new String[] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" }, 
    new String[] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" }, 
    new String[] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "e" } }; 

에 입력 맵을 변경하고 어떻게되는지보십시오.

어떤 종류의 Dijkstra's을 사용하는 것이 좋을 것입니다. 여기서 시작 위치로부터 거리의지도를 유지하십시오. 다 익스트라의는 다음과에 따라,

public static class Cell { 
    public int row;  
    public int col; 

    public Cell(int row, int col) { 
     this.row = row; 
     this.col = col;   
    } 

    @Override 
    public String toString() { 
     return "{" + row + ", " + col + "}"; 
    } 
} 

주요 알고리즘 :

나는 좌표를 처리 할 수있는 편리한 클래스 Cell을 소개했다. 그것은 처음부터 미로의 횡단을 따라갑니다. 즉 처음부터 거리 1의 모든 셀을 방문하고, 다음 라운드는 시작부터 거리 2에있는 모든 셀을 방문합니다.

경로를 찾는 일은 끝점 셀에서 시작하여 점차 줄어드는 거리를 따라 시작 셀로 돌아가는 문제입니다.

public static int shortestPath(String[][] map, Cell start, Cell end, 
                  Stack<Cell> path) { 
    // initialize distances array filled with infinity 
    int[][] distances = new int[map.length][]; 
    for (int i = 0; i < map.length; i++) { 
     distances[i] = new int[map[i].length]; 
     Arrays.fill(distances[i], Integer.MAX_VALUE); 
    } 

    // the start node should get distance 0 
    int distance = 0; 
    List<Cell> currentCells = Arrays.asList(start); 

    while (distances[end.row][end.col] == Integer.MAX_VALUE 
       && !currentCells.isEmpty()) { 
     List<Cell> nextCells = new ArrayList<>(); 

     // loop over all cells added in previous round 
     // set their distance 
     // and add their neighbors to the list for next round 
     for (Cell cell : currentCells) { 
      if (distances[cell.row][cell.col] == Integer.MAX_VALUE 
        && !map[cell.row][cell.col].equals("1")) { 
       distances[cell.row][cell.col] = distance; 
       addNeighbors(cell, nextCells, map.length, map[0].length); 
      } 
     } 

     // prepare for next round 
     currentCells = nextCells; 
     distance++; 
    } 

    // find the path 
    if (distances[end.row][end.col] < Integer.MAX_VALUE) { 
     Cell cell = end; 
     path.push(end); 
     for (int d = distances[end.row][end.col]-1; d >= 0; d--) { 
      cell = getNeighbor(cell, d, distances); 
      path.push(cell); 
     } 
    } 

    return distances[end.row][end.col]; 
} 

내가 알고리즘 간결을 유지하기 위해 몇 가지 유틸리티 메소드를 사용 :

public static void main(String[] args) { 
    String[][] map = new String[][] 
      { 
        new String[] { "1","1","1","0","0","0","1","1","1","1" }, 
        new String[] { "s","0","0","0","1","1","0","0","0","1" }, 
        new String[] { "1","1","0","0","1","0","0","1","0","1" }, 
        new String[] { "1","1","1","0","0","0","0","0","0","1" }, 
        new String[] { "1","0","1","1","1","0","1","1","0","1" }, 
        new String[] { "0","0","0","0","0","0","0","0","0","1" }, 
        new String[] { "0","1","1","1","1","1","1","1","1","1" }, 
        new String[] { "0","0","0","0","0","0","0","0","0","e" }, 
      }; 

    Stack<Cell> path = new Stack<>(); 
    System.out.println(shortestPath(map, new Cell(1, 0), new Cell(7, 9), path)); 

    while (!path.isEmpty()) { 
     System.out.print(path.pop() + ", "); 
    } 
} 

및 인쇄를 다음과 같이

// add all valid neighbors of a cell to the list 
    // where "valid" means: indices inside the maze 
private static void addNeighbors(Cell cell, List<Cell> list, 
             int maxRow, int maxCol) { 
    int[][] ds = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; 
    for (int[] d : ds) { 
     int row = cell.row + d[0]; 
     int col = cell.col + d[1];   
     if (isValid(row, col, maxRow, maxCol)) 
      list.add(new Cell(row, col)); 
    } 
} 

// find the neighbor of a cell having a certain distance from the start   
private static Cell getNeighbor(Cell cell, int distance, int[][] distances) { 
    int[][] ds = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; 
    for (int[] d : ds) { 
     int row = cell.row + d[0]; 
     int col = cell.col + d[1];   
     if (isValid(row, col, distances.length, distances[0].length) 
       && distances[row][col] == distance) 
      return new Cell(row, col);    
    } 
    return null; 
} 

// check if coordinates are inside the maze 
private static boolean isValid(int row, int col, int maxRow, int maxCol) { 
    return row >= 0 && row < maxRow && col >= 0 && col < maxCol; 
} 

내 주요 방법은

25 
{1, 0}, {1, 1}, {1, 2}, {1, 3}, {2, 3}, {3, 3}, {3, 4}, {3, 5}, {4, 5}, {5, 5}, 
{5, 4}, {5, 3}, {5, 2}, {5, 1}, {5, 0}, {6, 0}, {7, 0}, {7, 1}, {7, 2}, {7, 3}, 
{7, 4}, {7, 5}, {7, 6}, {7, 7}, {7, 8}, {7, 9}, 
1

셀의 위치를 ​​저장할 수있는 두 개의 필드 X와 Y가있는 Coordinate 클래스를 새로 만들 수 있습니다. 그런 다음 Coordinate의 목록을 매개 변수로 함수에 전달할 수 있습니다.

하지만 가장 효율적인 방법은 아닙니다. 성능 향상을 위해 선행 행렬을 사용합니다. 이러한 행렬에서는 현재 셀의 선행 위치 정보를 유지합니다. 하나의 셀에는 전임자가 하나만있을 수 있지만 여러 셀에는 동일한 셀이있을 수 있습니다.