簡體   English   中英

調試/修復 BFS 算法

[英]Debugging/fixing a BFS algorithm

我正在解決這個 BFS 作業問題,我相信我遵循的邏輯是正確的,但我陷入了無法確定的實現錯誤。 我正在尋求幫助調試此解決方案,而不是提出新的解決方案。

問題陳述:

一個孩子有兩個他遠程控制的機器人,兩個機器人都在 NxN 棋盤上,應該放在棋盤的 A 和 B 位置。

兩個機器人同時受到遠程 controller 的影響,相同的命令會影響它們的兩個狀態。

遙控器 controller 只能使兩個機器人同時順時針或逆時針轉動 90 度或命令兩個機器人向前移動。

示例:最左側的圖像顯示初始設置。 向右的箭頭是朝東的機器人,朝上的箭頭是朝北的機器人。 位置 A 和 B 是機器人的命運。

中心圖像顯示了將兩個機器人向前移動一步的結果。

右圖顯示了使機器人逆時針旋轉的結果。

圖1

孩子希望計算將機器人從初始位置帶到目的地所需的最少移動次數。

如果機器人被命令翻牆,它會留在原地。

如果兩個機器人被命令移動到同一個位置,它們將留在原來的位置。

圖 2 顯示了這種特殊情況。

在此處輸入圖像描述

兩個機器人應該同時到達不同的命運。

輸入:輸入由各種測試用例組成,第一行以 integer 開頭,輸入矩陣(棋盤)的大小為 N,2<= N <=25。

以下 N 行描述了棋盤格,每行有 N 個字符。

一個 '。' 表示一個空的 position。

N、E、S 或 O(西班牙語為 Oeste=West)表示機器人的原始位置和方向。

D 表示棋盤中機器人的命運,“*”表示障礙物。

輸入以 N=0 的情況結束。

輸入.txt

5
D....
N...S
.....
*...*
....D
5
.....
S..S.
.....
.....
D..D.
3
SN.
***
.DD
0

為 input.txt 正確的 output:

8
3
-1

輸入2.txt:

5
.....
..D.S
.D...
.....
..N..
6
......
..S...
......
.ED...
......
.D....
11
....E......
....D......
...........
..S...D....
...........
...........
...........
...........
...........
...........
...........
13
.............
.............
.............
.............
.....N.......
.............
.........D...
..D..........
.............
...E.........
.............
.............
.............
25
...*.......*.*...........
........*..D...*.**....*.
*..*.*.........*..*..*..D
...*.**.*........*...*...
......**..*..***.***...**
.............*...........
....*...***.....*.**.....
......**.......**.*.*...*
.........*..*...*.*......
....**.*.*....**.*.*.*.*.
.......*............**...
..........*.*.....*......
...........**....*.**....
.....E.*.*..........**.*.
.........*.*.*.*..*..*...
*........**...*..........
................***..*...
........*....*....*...*..
......*...*.*...*.....**.
...*..........*.**.......
.**............*.*..*.*..
........*........*...*...
*......*..........*......
*...*......N*......*..*.*
.    .....*..*.*..*...*......
0

“正確”(?)output for input2.txt:

-1
-1
9
-1
46

我的解決方案:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;




class Position {

    int i;
    int j;
    char orientation;

        Position() {

    }


    void setIJ(int i, int j){
        this.i=i;
        this.j=j;
    }

    void setOrientation(char c){

        orientation = c;
    }

   public boolean equals(Object o){

        if(o instanceof Position){

          Position p = (Position)o;
          if((p.i==this.i)&&(p.j==this.j)&&(p.orientation==this.orientation))
          {
              return true;
          }
              else return false;
          }

            return false;
   }

} //end class Position


class TransitionState {

    Position positionA;
    Position positionB;

    int counter;

    public boolean equals (Object o){

        if (o instanceof TransitionState){

          TransitionState transitionState= (TransitionState)o;

          if ((this.positionA.equals(transitionState.positionA))
                  &&(this.positionB.equals(transitionState.positionB)))
          {
              return true;
          }
        }
     return false;

    }

}


public class Robots {

static Position moveForward(Position oldPosition, int matrixSize, char orientation, char [][] inputMatrix){

     // add possible new Position
    Position newPosition= new Position();

    //first return oldPosition in border positions in which the robot shouldn't move

    if ((orientation=='O')&&(oldPosition.j==0))
           return oldPosition;

    if ((orientation=='E')&&(oldPosition.j==(matrixSize-1)))
           return oldPosition;

     if ((orientation=='N')&&(oldPosition.i==0))
           return oldPosition;

     if ((orientation=='S')&&(oldPosition.i==(matrixSize-1)))
           return oldPosition;


     if ((orientation=='O'))
         newPosition.setIJ(oldPosition.i, oldPosition.j-1);
     if ((orientation=='E'))
         newPosition.setIJ(oldPosition.i, oldPosition.j+1);
    if ((orientation=='S'))
         newPosition.setIJ(oldPosition.i-1, oldPosition.j);
    if ((orientation=='N'))
         newPosition.setIJ(oldPosition.i+1, oldPosition.j);


    //return oldPosition for positions in which the robot is blocked by *
    if (inputMatrix[newPosition.i][newPosition.j]=='*'){
        return oldPosition;
    }

    return newPosition; // if it got here, all ok

}


static char turnCounter (char orientation){

     if(orientation=='N')
         return 'O';
     if(orientation=='O')
         return 'S';
     if (orientation=='S')
         return 'E';
     else
         return 'N';

 }

static char turnClock(char orientation){

      if(orientation=='N')
         return 'E';
     if(orientation=='E')
         return 'S';
         if (orientation=='S')
         return 'O';
     else
         return 'N';

 }

static Position[] robotInitialPositions(char [][]inputMatrix){

     Position [] helperArray = new Position[2];

     int aux=0;

     for (int i=0; i<(inputMatrix[0].length); i++)
         for (int j=0; j<(inputMatrix[0].length); j++)
         {
            if((inputMatrix[i][j]=='N')||(inputMatrix[i][j]=='S')||(inputMatrix[i][j]=='O')||(inputMatrix[i][j]=='E'))
            {
                    helperArray[aux]= new Position();
                    helperArray[aux].setIJ(i, j);
                    if (inputMatrix[i][j]=='N'){helperArray[aux].orientation='N'; }
                    if (inputMatrix[i][j]=='S'){helperArray[aux].orientation='S'; }
                    if (inputMatrix[i][j]=='E'){helperArray[aux].orientation='E'; }
                    if (inputMatrix[i][j]=='O'){helperArray[aux].orientation='O'; }
                    aux= aux+1;
            }

         }

     return helperArray;

 }


static Position[] getDestinies(char [][]inputMatrix){

     Position [] helperArray = new Position[2];

     int aux=0;

     for (int i=0; i<(inputMatrix[0].length); i++)
         for (int j=0; j<(inputMatrix[0].length); j++)
         {
            if((inputMatrix[i][j]=='D'))
            {
                    helperArray[aux]= new Position();
                    helperArray[aux].i=i; helperArray[aux].j=j;
                    helperArray[aux].orientation='D';
                    aux=aux+1;

            }

         }

     return helperArray;

 }



static boolean [][]getUnvisitedMatrix(int matrixLength){


   boolean[][] unvisitedMatrix = new boolean [matrixLength][matrixLength];

    for (int i=0; i<matrixLength;i++)
        for (int j=0; j<matrixLength; j++)
            unvisitedMatrix[i][j]=false;

    return unvisitedMatrix;

}





static Position[]getNewRobotPositions (Position oldR1Pos,Position oldR2Pos, String movement, char [][]inputMatrix){

    Position[]newPositions = new Position[2];

    Position newR1Pos = new Position();
        Position newR2Pos = new Position();

    if(movement.equals("counter")){

        if (oldR1Pos.orientation=='N'){

            newR1Pos.orientation='O';

        }

        if (oldR1Pos.orientation=='S'){

            newR1Pos.orientation='E';

        }

        if (oldR1Pos.orientation=='E'){

            newR1Pos.orientation='N';

        }

        if (oldR1Pos.orientation=='O'){

            newR1Pos.orientation='S';
        }


        if (oldR2Pos.orientation=='N'){

            newR2Pos.orientation='O';
        }

        if (oldR2Pos.orientation=='S'){

            newR2Pos.orientation='E';

        }

        if (oldR2Pos.orientation=='E'){

            newR2Pos.orientation='N';

        }

        if (oldR2Pos.orientation=='O'){

            newR2Pos.orientation='S';

        }

        newR1Pos.i=oldR1Pos.i;
        newR1Pos.j=oldR1Pos.j;

        newR2Pos.i=oldR2Pos.i;
        newR2Pos.j=oldR2Pos.j;

        newPositions[0]=newR1Pos;
        newPositions[1]=newR2Pos;

//        System.out.println("MOVED COUNTERCLOCKWISE");
//        System.out.println("previous Robot 1 position was "+oldR1Pos.i + ","+oldR1Pos.j + " orientation was " + oldR1Pos.orientation +
//        " new Robot 1 position is " + newR1Pos.i + "," + newR1Pos.j+ " orientation is "+newR1Pos.orientation);
//
//        System.out.println("previous Robot 2 position was "+oldR2Pos.i + ","+oldR2Pos.j + " orientation was " + oldR2Pos.orientation +
//        " new Robot 2 position is " + newR2Pos.i + "," + newR2Pos.j+ " orientation is "+newR2Pos.orientation);

        return newPositions;


    }

    if(movement.equals("clock")){

        newR1Pos.i = oldR1Pos.i;
        newR1Pos.j = oldR1Pos.j;

        newR2Pos.i = oldR2Pos.i;
        newR2Pos.j = oldR2Pos.j;


        if (oldR1Pos.orientation=='N'){

             newR1Pos.orientation= 'E';
        }

        if (oldR1Pos.orientation=='S'){

             newR1Pos.orientation= 'O';
        }

        if (oldR1Pos.orientation=='E'){

             newR1Pos.orientation= 'S';
        }

        if (oldR1Pos.orientation=='O'){

             newR1Pos.orientation= 'N';

        }



        if (oldR2Pos.orientation=='N'){

             newR2Pos.orientation= 'E';
        }

        if (oldR2Pos.orientation=='S'){

             newR2Pos.orientation= 'O';

        }

        if (oldR2Pos.orientation=='E'){

             newR2Pos.orientation= 'O';

        }

        if (oldR2Pos.orientation=='O'){

             newR2Pos.orientation= 'N';

        }
//        System.out.println("MOVED CLOCKWISE");
//        System.out.println("previous Robot 1 position was "+oldR1Pos.i + ","+oldR1Pos.j + " orientation was " + oldR1Pos.orientation +
//        " new Robot 1 position is " + newR1Pos.i + "," + newR1Pos.j+ " orientation is "+newR1Pos.orientation);
/    /
//        System.out.println("previous Robot 2 position was "+oldR2Pos.i + ","+oldR2Pos.j + " orientation was " + oldR2Pos.orientation +
//        " new Robot 2 position is " + newR2Pos.i + "," + newR2Pos.j+ " orientation is "+newR2Pos.orientation);


        newPositions[0]=newR1Pos;
        newPositions[1]=newR2Pos;

        return newPositions;

    }

    if(movement.equals("forward")){

        //default case, if conditions not satisfied
        newR1Pos.i=oldR1Pos.i;
        newR1Pos.j=oldR1Pos.j;
            newR1Pos.orientation = oldR1Pos.orientation;

        newR2Pos.i=oldR2Pos.i;
        newR2Pos.j=oldR2Pos.j;
        newR2Pos.orientation = oldR2Pos.orientation; 


        if(oldR1Pos.orientation=='N'){

            if(oldR1Pos.i-1>=0){   //doesn't exceed the upper border

               //doesn't collide with '*'
               if (inputMatrix[oldR1Pos.i-1][oldR1Pos.j]!='*'){
                        newR1Pos.i=oldR1Pos.i-1;
                        newR1Pos.j=oldR1Pos.j;
                        newR1Pos.orientation = oldR1Pos.orientation;
               }

            }

        }

         if(oldR1Pos.orientation=='S'){

             if(oldR1Pos.i+1<inputMatrix.length){   //doesn't exceed the lower border

               //doesn't collide with '*'
               if (inputMatrix[oldR1Pos.i+1][oldR1Pos.j]!='*'){
                        newR1Pos.i=oldR1Pos.i+1;
                        newR1Pos.j=oldR1Pos.j;
                        newR1Pos.orientation = oldR1Pos.orientation;

               }
           }
        }

         if(oldR1Pos.orientation=='E'){

             if(oldR1Pos.j+1<inputMatrix.length){   //doesn't exceed the right border

               //doesn't collide with '*'
               if (inputMatrix[oldR1Pos.i][oldR1Pos.j+1]!='*'){
                        newR1Pos.i=oldR1Pos.i;
                        newR1Pos.j=oldR1Pos.j+1;
                        newR1Pos.orientation = oldR1Pos.orientation;
               }
           }

        }

        if(oldR1Pos.orientation=='O'){

             if(oldR1Pos.j-1>=0){   //doesn't exceed the left border

               //doesn't collide with '*'
               if (inputMatrix[oldR1Pos.i][oldR1Pos.j-1]!='*'){
                        newR1Pos.i=oldR1Pos.i;
                        newR1Pos.j=oldR1Pos.j-1;
                        newR1Pos.orientation = oldR1Pos.orientation;
               }

            }

        }

        //same for robot 2

       if(oldR2Pos.orientation=='N'){

            if(oldR2Pos.i-1>=0){   //doesn't exceed the upper border

               //doesn't collide with '*'
               if (inputMatrix[oldR2Pos.i-1][oldR2Pos.j]!='*'){
                        newR2Pos.i=oldR2Pos.i-1;
                        newR2Pos.j=oldR2Pos.j;
                        newR2Pos.orientation=oldR2Pos.orientation;
               }

            }

        }

         if(oldR2Pos.orientation=='S'){

             if(oldR2Pos.i+1<inputMatrix.length){   //doesn't exceed the lower border

               //doesn't collide with '*'
               if (inputMatrix[oldR2Pos.i+1][oldR2Pos.j]!='*'){
                        newR2Pos.i=oldR2Pos.i+1;
                        newR2Pos.j=oldR2Pos.j;
                        newR2Pos.orientation=oldR2Pos.orientation;
               }
           }
        }

         if(oldR2Pos.orientation=='E'){

             if(oldR2Pos.j+1<inputMatrix.length){   //doesn't exceed the right border

               //doesn't collide with '*'
               if (inputMatrix[oldR2Pos.i][oldR2Pos.j+1]!='*'){
                        newR2Pos.i=oldR2Pos.i;
                        newR2Pos.j=oldR2Pos.j+1;
                        newR2Pos.orientation=oldR2Pos.orientation;
               }
           }

        }

        if(oldR2Pos.orientation=='O'){

             if(oldR2Pos.j-1>=0){   //doesn't exceed the left border

               //doesn't collide with '*'
               if (inputMatrix[oldR2Pos.i][oldR2Pos.j-1]!='*'){
                        newR2Pos.i=oldR2Pos.i;
                        newR2Pos.j=oldR2Pos.j-1;
                        newR2Pos.orientation=oldR2Pos.orientation;
               }

            }

        }


        //if robots collide in new positions, revert to their original positions
        if ((newR1Pos.i==newR2Pos.i) && (newR1Pos.j==newR2Pos.j)){

            //revert robot 1 position
             newR1Pos.i=oldR1Pos.i;
             newR1Pos.j=oldR1Pos.j;
             newR1Pos.orientation = oldR1Pos.orientation;

             //revert robot 2 position
             newR2Pos.i=oldR2Pos.i;
             newR2Pos.j=oldR2Pos.j;
             newR2Pos.orientation = oldR2Pos.orientation;
        }

        newPositions[0] = newR1Pos;
        newPositions[1] = newR2Pos;

//        System.out.println("MOVED FORWARD");
//         System.out.println("previous Robot 1 position was "+oldR1Pos.i + ","+oldR1Pos.j + " orientation was " + oldR1Pos.orientation +
//        " new Robot 1 position is " + newR1Pos.i + "," + newR1Pos.j+ " orientation is "+newR1Pos.orientation);
//
//        System.out.println("previous Robot 2 position was "+oldR2Pos.i + ","+oldR2Pos.j + " orientation was " + oldR2Pos.orientation +
//        " new Robot 2 position is " + newR2Pos.i + "," + newR2Pos.j+ " orientation is "+newR2Pos.orientation);

    } //end movement.equals("forward")


    return newPositions;

}


//1  procedure BFS(Graph,source):
//2      create a queue Q
//3      enqueue source onto Q
//4      mark source
//5      while Q is not empty:
//6          dequeue an item from Q into v
//7          for each edge e incident on v in Graph:
//8              let w be the other end of e
//9              if w is not marked:
//10                 mark w
//11                 enqueue w onto Q



 static void BFS (char [][] inputMatrix){

    ArrayList<TransitionState> transitionStatesArray = new ArrayList<TransitionState>();

    int moveCounter=0; //turns and forward movements add here

    int tempMoveCounterRobot1=0; int tempMoveCounterRobot2=0;
    int maxMoveCounter=0;

    PositionsAndCounter positionsAndCounter= new PositionsAndCounter();

    Queue <PositionsAndCounter>queue = new LinkedList<PositionsAndCounter>();

    Position robotInitial[] = robotInitialPositions(inputMatrix); //get source
    positionsAndCounter.positionPair=robotInitial; //used to encapsulate the positions with a counter to output
    positionsAndCounter.counter=0;//first initialize to 0

    Position destinies[] = getDestinies(inputMatrix); //get destinies


    TransitionState firstTransitionState = new TransitionState();
    firstTransitionState.positionA=robotInitial[0];
    firstTransitionState.positionB=robotInitial[1];

    transitionStatesArray.add(firstTransitionState);

    //mark transition used , if the transition is new, it should be queued

    queue.add(positionsAndCounter);

    String [] movement =  {"forward", "counter", "clock"}; 
    //possible movements inside inputMatrix


    outer: while (!queue.isEmpty()){ //while queue is not empty

         PositionsAndCounter v= queue.poll(); //dequeue an item from Q into V

         for(int k = 0; k<3; k++){ //for each edge e incident on v in Graph:

            Position[] newRobotPositions = getNewRobotPositions(v.positionPair[0], v.positionPair[1], movement[k], inputMatrix);

            TransitionState newTransitionState = new TransitionState();
            newTransitionState.positionA=newRobotPositions[0];
            newTransitionState.positionB=newRobotPositions[1];

            if(!transitionStatesArray.contains(newTransitionState)){  //if the transition state is new add and enqueue new robot positions

                 transitionStatesArray.add(newTransitionState);

                   //if transition is new then queue
                 PositionsAndCounter newPositionsAndCounter = new PositionsAndCounter();
                 newPositionsAndCounter.positionPair=newRobotPositions;
                 newPositionsAndCounter.counter = v.counter +1;


                  queue.add(newPositionsAndCounter);


             }


             inputMatrix[v.positionPair[0].i][v.positionPair[1].j]='.'; 
             inputMatrix[v.positionPair[1].i][v.positionPair[1].j]='.';

             //inputMatrix[v[0].i][v[0].j]='.'; // mark old position of robot 1 with .
             //inputMatrix[v[1].i][v[1].j]='.'; // mark old position of robot 2 with .

             //update new robot positions
             inputMatrix[newRobotPositions[0].i][newRobotPositions[0].j]= newRobotPositions[0].orientation;
             inputMatrix[newRobotPositions[1].i][newRobotPositions[1].j]= newRobotPositions[1].orientation;


             //check if solution has been found
                   if
                   (
                   ((destinies[0].i==newRobotPositions[0].i)&&(destinies[0].j==newRobotPositions[0].j) //robot in 0 arrived to destiny
                   || (destinies[1].i==newRobotPositions[0].i)&&(destinies[1].j==newRobotPositions[0].j))// in 0 or 1
                        &&                                                                                                      //and 
                  ((destinies[0].i==newRobotPositions[1].i)&&(destinies[0].j==newRobotPositions[1].j) //robot in 1 arrived to destiny
                  || (destinies[1].i==newRobotPositions[0].i)&&(destinies[1].j==newRobotPositions[0].j))//in 0 or 1

                   ) //end if
                   {

                      System.out.println("robots arrived at destinies");
                      System.out.println("robot 1, starting at " + robotInitial[0].i + "," + robotInitial[0].j
                               + " is in " + newRobotPositions[0].i + ","+ newRobotPositions[0].j);
                      System.out.println("robot 2, starting at " + robotInitial[1].i + "," + robotInitial[1].j
                               + " is in " + newRobotPositions[1].i + ","+ newRobotPositions[1].j);

                     System.out.println("movements: " + (v.counter));

                     return;
                     //break outer;

                   }


                }

            }

            System.out.println("robots can never arrive at their destinies");
            System.out.println(-1);


    }


static void printInputMatrix(char [][] inputMatrix){


    for (int i=0; i<inputMatrix[0].length;i++)
        for(int j=0; j<inputMatrix[0].length;j++)
        {

            System.out.print(" "+inputMatrix[i][j]+" ");
            if(j==inputMatrix[0].length-1){System.out.println("");}

        }


}





    public static void main(String[] args) throws IOException {

//        System.out.println("Test transition checker");
//        Position p1 = new Position();
//        p1.i=1;
//        p1.j=1;
//        p1.orientation='N';
//        Position p2 = new Position();
//        p2.i=1;
//        p2.j=2;
//        p2.orientation='N';
//        Position p3 = new Position();
//        p3.i=1;
//        p3.j=1;
//        p3.orientation='N';
//        Position p4 = new Position();
//        p4.i=1;
//        p4.j=1;
//        p4.orientation='N';
//
//        TransitionState transitionChecker1 = new TransitionState();
//        transitionChecker1.positionA=p1;
//        transitionChecker1.positionB=p2;
//
//        TransitionState transitionChecker2 = new TransitionState();
//        transitionChecker2.positionA=p1;
//        transitionChecker2.positionB=p2;
//
//
//        ArrayList<TransitionState> arrayTransitions = new ArrayList<TransitionState>();
//        arrayTransitions.add(transitionChecker1);
//        System.out.println("Test contains? " + arrayTransitions.contains(transitionChecker2));




        BufferedReader br = new BufferedReader(new FileReader(new File("input.txt")));

        char [][] inputMatrix;

        String line;
        char [] lineAsCharArray;
        int matrixSize;

        while(true){

            line = br.readLine();
            matrixSize=Integer.parseInt(line);

            inputMatrix = new char [matrixSize][matrixSize];

            if (matrixSize==0){  // end outer looping
                break;
            }

            else { //begin inner looping

                for (int i=0; i<matrixSize; i++){

                    line = br.readLine();
                    inputMatrix[i] =line.toCharArray();

                }

                //matrix loaded

                BFS(inputMatrix);

            }


        }

    }

}

class PositionsAndCounter {

    Position[] positionPair;
    int counter;

    PositionsAndCounter() {
        positionPair = new Position[2];
        counter=0;

    }
}

問題: 1)在第一個 input.txt 文件中,找到了 9 個動作來找到第一道菜的解(什么時候應該是 8)和 6 個動作來找到第二道菜的解(什么時候應該是 3)。最后(不可能的)課程配置正確打印出 -1。

2)在第二個 input.txt 文件中,教授說它應該為第一門課程打印 -1 和 -1,盡管我的程序為第二種情況找到了一個合理的解決方案,而為第一種情況找到了一個奇怪的解決方案(這是我認為一個更有經驗的調試器可以提供幫助,我不知道第一種情況下流離失所的命運 output 的原因)。 我的教授提出的輸出正確嗎? 我的算法也卡在應該打印 46 的情況下。

有2個不小心的復制粘貼問題導致代碼不工作,1、在順時針轉動部分:

        if (oldR2Pos.orientation == 'E') {

            newR2Pos.orientation = 'O';

        }

這是錯誤的……應該是從上面的塊直接復制粘貼

        if (oldR2Pos.orientation == 'E') {

            newR2Pos.orientation = 'S';
        }

然而你卻錯過了。

另一個問題實際上是在結束條件測試塊

     //check if solution has been found
           if
           (
           ((destinies[0].i==newRobotPositions[0].i)&&(destinies[0].j==newRobotPositions[0].j) //robot in 0 arrived to destiny
           || (destinies[1].i==newRobotPositions[0].i)&&(destinies[1].j==newRobotPositions[0].j))// in 0 or 1
                &&                                                                                                      //and 
          ((destinies[0].i==newRobotPositions[1].i)&&(destinies[0].j==newRobotPositions[1].j) //robot in 1 arrived to destiny
          || **(destinies[1].i==newRobotPositions[0].i)&&(destinies[1].j==newRobotPositions[0].j)**)//in 0 or 1

           ) //end if

最后一部分(代碼突出顯示)應該是

(destinies[1].i==newRobotPositions[1].i)&&(destinies[1].j==newRobotPositions[1].j)

這顯然是復制和粘貼但忘記更改錯誤。 邏輯有點難以理解,但有效,

(X 中的 A 或 Y 中的 B)和(Y 中的 A 或 X 中的 B)

雖然它是相同的(邏輯上不完全一樣,但它在你的情況下是如何工作的,因為 A 和 B 不能占據相同的位置),如果你使用它會更清楚

(X 中的 A 和 Y 中的 B)或(Y 中的 A 和 X 中的 B)

除了上面提到的致命錯誤之外,您的程序還有一些其他問題需要解決。看起來您是一名學習計算機科學的大學生,請在編碼前閱讀給定的源代碼:TransistionState class is not used but you創建了您自己的 PositionsAndCounter,翻轉邏輯實現了兩次,如果您沒有重寫翻轉代碼並使用給定的代碼,您將不會提交問題 1....如果我是您的教授,我可能會讓您失望. 在敲擊鍵盤之前計划好您的解決方案,並確保您的代碼清晰易讀,如果您盯着源代碼 5 分鍾並且無法弄清楚代碼塊的用途,可能是您沒有正確地構造它。

下面的清單是您問題的示例解決方案:

import java.awt.Point;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;


public class DualRobot {

    public enum Orientation{
        E(1, 0), S(0, 1), O(-1, 0), N(0, -1);

        public final int dx, dy;
        private Orientation(int dx, int dy){
            this.dx = dx;
            this.dy = dy;
        }

        public Orientation left(){
            return Orientation.values()[(this.ordinal() + 3) % 4];
        }

        public Orientation right(){
            return Orientation.values()[(this.ordinal() + 1) % 4];
        }

        public static Orientation valueOf(char c){
            for(Orientation o : Orientation.values()){
                if(o.toString().equalsIgnoreCase("" + c)) return o;
            }
            return null;
        }

    }

    public enum Action {FORWARD, COUNTER_CLOCKWISE, CLOCKWISE}; // F: forward, L: Counter clockwise, R: clockwise

    private static class Robot{
        Point position;
        Orientation orientation;

        public Robot(Robot r){
            this.position = new Point(r.position);
            this.orientation = r.orientation;
        }
        public Robot(int x, int y, Orientation orientation){
            this.position = new Point(x, y);
            this.orientation = orientation;
        }

        public void move(Action action, char[][] map){
            switch (action) {
            case FORWARD:
                Point nextPosition = new Point(position);
                nextPosition.translate(orientation.dx, orientation.dy);
                if(isValidPosition(nextPosition, map)) position = nextPosition;
                break;
            case COUNTER_CLOCKWISE:
                this.orientation = this.orientation.left();
                break;
            case CLOCKWISE:
                this.orientation = this.orientation.right();
                break;
            }
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof Robot) {
                Robot r = (Robot) obj;
                return r.position.equals(this.position) && r.orientation == this.orientation;
            }
            return super.equals(obj);
        }

        @Override
        public int hashCode() {
            return orientation.ordinal() + position.x * 10 + position.y * 1000;
        }

        private boolean isValidPosition(Point p, char[][] map){
            return p.x >= 0 && p.x < map[0].length 
                && p.y >= 0 && p.y < map.length
                && map[p.y][p.x] != '*';
        }
    }

    private static class State{
        private Robot a, b;
        private int counter;

        public State(Robot a, Robot b, int counter) {
            this.a = new Robot(a);
            this.b = new Robot(b);
            this.counter = counter;
        }

        public List<State> nextStates(char[][] map){
            List<State> states = new ArrayList<State>();
            for(Action action : Action.values()){
                State s = new State(this.a, this.b, this.counter + 1);
                s.a.move(action, map);
                s.b.move(action, map);
                if(!s.a.position.equals(s.b.position)){ // Test for collision
                    states.add(s);
                }
            }
            return states;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof State) {
                State state = (State) obj; // Consider the state to be the same if the 2 robots are at identical location and orientation
                return (this.a.equals(state.a) && this.b.equals(state.b))
                    || (this.a.equals(state.b) && this.b.equals(state.a));
            }
            return super.equals(obj);
        }

        @Override
        public int hashCode() {
            // The quality of this hashCode can affect the program's speed
            // Multiply is transitive, so if you swap a and b, the hashcode is the same
            return a.hashCode() * b.hashCode();
        }

    }

    public static void main(String[] args) throws IOException {
        BufferedReader input = new BufferedReader(new FileReader("input.txt"));
        int size;

        while((size = Integer.parseInt(input.readLine())) > 0){
            // Load the data;
            char[][] map = new char[size][size];
            for (int i = 0; i < size; i++) {
                map[i] = input.readLine().toCharArray();
            }

            // Construct initial state
            List<Robot> robots = new ArrayList<Robot>();
            List<Point> destinations = new ArrayList<Point>();
            for(int i = 0; i < size; i ++){
                for(int j = 0; j < size; j ++){
                    Orientation orientation = Orientation.valueOf(map[i][j]);
                    if(orientation != null){
                        robots.add(new Robot(j, i, orientation));
                    }else if(map[i][j] == 'D'){
                        destinations.add(new Point(j, i));
                    }
                }
            }

            System.out.println(BFSSearch(map, new State(robots.get(0), robots.get(1), 0), destinations));

        }

    }

    private static int BFSSearch(char[][] map, State initialState, List<Point> destinations) throws IOException{
        List<State> queue = new LinkedList<State>(); // Array list is slightly more efficient
        queue.add(initialState); // Initial state
        Map<State, Boolean> testedStates = new HashMap<State, Boolean>();
        while(queue.size() > 0){
            State currentState = queue.remove(0);
            if(testedStates.containsKey(currentState)) continue;

            // Testing for end condition
            if((currentState.a.position.equals(destinations.get(0)) && currentState.b.position.equals(destinations.get(1)))
            || (currentState.a.position.equals(destinations.get(1)) && currentState.b.position.equals(destinations.get(0)))){
                return currentState.counter;
            }
            testedStates.put(currentState, true);
            queue.addAll(currentState.nextStates(map));
        }
        return -1;
    }   
}

這個程序在大約 10 秒內吐出了最終答案。

主要區別是我使用了 hash 表來存儲測試狀態以提高速度,因此 hash function 的質量會對速度產生影響。

推薦閱讀:hash表,DRY原理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM