【发布时间】: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