【问题标题】:Knight's tour using Graph(DFS) Java使用 Graph(DFS) Java 的骑士之旅
【发布时间】:2022-01-03 01:31:15
【问题描述】:

我正在尝试使用 DFS 实现骑士之旅。为简单起见,我的板是 5x5。

下面是我的代码

class StackK
   {
   private final int SIZE = 25;
   private int[] st;
   private int top;
// ------------------------------------------------------------
   public boolean isFull()
   {return (top == SIZE-1);}
// ------------------------------------------------------------
   public StackK()           // constructor
      {
  st = new int[SIZE];    // make array
  top = -1;
  }
  public void push(int j)   // put item on stack
      { st[++top] = j; }
// ------------------------------------------------------------
   public int pop()          // take item off stack
  { return st[top--]; }
// ------------------------------------------------------------
   public int peek()         // peek at top of stack
  { return st[top]; }
// ------------------------------------------------------------
   public boolean isEmpty()  // true if nothing on st   ack
      { return (top == -1); }
// ------------------------------------------------------------
   }  // end class StackK
////////////////////////////////////////////////////////////////

class VertexK
   {
   public String label;        // label (e.g. 'A')
   public boolean wasVisited;
   public int lastVisited;
// ------------------------------------------------------------
   public VertexK()   // constructor
      {
      label = "O";
      wasVisited = false;
      lastVisited = 0;
      }
// ------------------------------------------------------------
   }  // end class VertexK
////////////////////////////////////////////////////////////////
class GraphK
   {
   private final int SIZE = 5;
   private final int AREA = 5*5;
   private VertexK vertexList[]; // list of vertices
   private int adjMat[][];      // adjacency matrix
   private int nVerts;          // current number of vertices
   private StackK theStack;


// ------------------------------------------------------------
   public GraphK()               // constructor
      {
      vertexList = new VertexK[AREA];// chess board


  adjMat = new int[AREA][AREA];// adjacency matrix


  nVerts = 0; // number of vertices

  for(int y=0; y<SIZE; y++)      // set adjacency
     for(int x=0; x<SIZE; x++)   //    matrix to 0
        adjMat[x][y] = 0;

  theStack = new StackK(); //initialize stack


  for(int i=0;i<AREA;i++)  // make a chess board
       addVertex();


  for(int i = 0; i < SIZE; i++) // add all possible moves to adjMat
        for(int j = 0; j < SIZE; j++)
            addMoves(i, j);
  }
// ---------------------------------------------------------------
   public void displayBoard(){
   int count =0;
   for(int i=0;i<5;i++){
       for(int j=0;j<5;j++){
           System.out.print(vertexList[(count+j)].label+" ");
       }
       count = count+5;
       System.out.println("");
   }
   System.out.println("----------------------------------------------");
   }
// ---------------------------------------------------------------
   public void addMoves(int i, int j)
    {
    int currentRow = i*SIZE; //row
    int currentCol = j; //col
    int currentVertex = currentRow+currentCol;

    if(i-1>=0){
        if(j-2>=0){
            addEdge(currentVertex,currentVertex-SIZE-2);
        }
        if(j+2<SIZE){
            addEdge(currentVertex,currentVertex-SIZE+2);
        }
    }
    if(i+1<SIZE)
    {
        if(j-2>=0){
            addEdge(currentVertex, currentVertex+SIZE-2);
        }
        if(j+2<SIZE){
            addEdge(currentVertex, currentVertex+SIZE+2);
        }
    }
    if(i-2>=0){
        if(j-1>=0){
            addEdge(currentVertex, currentVertex-(SIZE*2)-1);
        }
        if(j+1<SIZE){
            addEdge(currentVertex,currentVertex-(SIZE*2)+1);
        }

    }
    if(i+2<SIZE){
        if(j-1>=0){
            addEdge(currentVertex,currentVertex+(SIZE*2)-1);
        }
        if(j+1<SIZE){
            addEdge(currentVertex,currentVertex+(SIZE*2)+1);
        }
    }


}


// ------------------------------------------------------------
   public void addVertex()
      {
      vertexList[nVerts++] = new VertexK();
      }
// ------------------------------------------------------------
   public void addEdge(int start, int end)
      {
      adjMat[start][end] = 1;
      }


// ------------------------------------------------------------
   public void dfs()  // depth-first search
   {                                 
   vertexList[0].wasVisited = true;  
   vertexList[0].label = "V";                
   theStack.push(0);


   while( !theStack.isEmpty() )      
  {
  if(theStack.isFull()){
      System.out.println("You Win");
  }
  int last = theStack.peek();
  int v = getNext( theStack.peek() );

  if(v == -1){

     System.out.println("DEAD END HERE");
     theStack.pop();
     vertexList[last].label = "O";
     displayBoard();

  }
  else                           
     {

     vertexList[v].label = "V";
     displayBoard();
     vertexList[v].lastVisited = last;
     vertexList[v].wasVisited = true;  

     theStack.push(v);                
     }
  }  // end while

   // stack is empty, so we're done
       }

  // ------------------------------------------------------------
 // returns an unvisited VertexK adj to v
 public int getNext(int v)
   {
   for(int j=0; j<nVerts; j++)
      if(adjMat[v][j]==1 && vertexList[j].wasVisited==false)
     return j;
   return -1;
   }  // end getAdjUnvisitedVertexK()
 // ------------------------------------------------------------
     public void displayAdj()
 {
    for(int i=0;i<AREA;i++){
    System.out.print(i+"th row: ");
    for(int k=0;k<AREA;k++)
        System.out.print(adjMat[i][k]);
    System.out.println("");
    }
 }
// ------------------------------------------------------------
   }  // end class GraphK

public class KnightApp
   {
   public static void main(String[] args)
  {
  GraphK k = new GraphK();

  k.displayAdj();
  k.dfs();
  k.displayBoard();


  }  // end main()
   }  // end class DFSApp

我的程序从索引 0 开始,然后转到索引 7,如果你运行代码你会注意到,这不是正确的解决方案(我还递归地编写了 knight's tour 来检查我应该从哪里开始得到正确的解决方案) .所以它应该一直回溯到起始方块 0,0 并转到索引 11,而不是它只是停止,因为当 theStack 为空时 while 循环结束。当它一直回溯到起点时,我怎样才能让它继续前进,以及如何在回溯时再次将访问过的方块标记为假。举起 TJE 班

提前谢谢你。

【问题讨论】:

  • 如果您不需要自己实现堆栈,您可能需要查看Deque。您是否掌握了棋盘上每个领域的可能动作?可能您需要删除您来自的字段(在回溯时)并尝试列表中的下一个。顺便说一句,将发布的代码减少到真正有问题的部分不仅可以帮助您调试它,还可以增加获得有用答案的机会。
  • 实现堆栈确实没有必要,但我认为其他部分对整体来说是必不可少的,这就是我包含整个代码的原因。我在回溯时遇到问题。
  • 您不需要显式堆栈。相反,您可以只使用递归,这使得解决方案更加更具可读性
  • 一种可能的算法与您的堆栈方法是:字段 0 - 查看您有哪些可能的目标字段 - 将它们保存到字段 0 - 转到列表中的第一个 - 如果您没有目标字段字段 1 - 返回字段 0,从可能的目的地列表中删除字段 1 - 转到列表中的下一个字段...

标签: java algorithm data-structures knights-tour


【解决方案1】:

当你发现一个死胡同时,你需要将当前顶点的 wasVisted 设置为 false,将其从其(当前的)最后一个顶点的邻接中移除,并将其(当前的)lastVistied 设置为零: 所以现在方法 dfs 中的 if 条件将是:

if (v == -1) {
    System.out.println("DEAD END HERE");
    theStack.pop();
    vertexList[last].label = "O";
    vertexList[last].wasVisited = false;
    adjMat[vertexList[last].lastVisited][last] = 0;
    vertexList[last].lastVisited = 0;
    displayBoard();
}

【讨论】:

  • 请告诉我它是否有效?在我结束后,它从 7 回溯后从 0 变为 11
猜你喜欢
  • 1970-01-01
  • 2014-01-12
  • 1970-01-01
  • 1970-01-01
  • 2015-04-06
  • 2015-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多