陷入N皇后java算法。(回溯)
有人能给我一个关于java程序的提示或指导吗?我陷入了回溯的想法。这是代码。如果你看一下solve()方法,它会递归地调用自己,但是我被困在一个点上,它无法放置更多的皇后,并试图回溯陷入N皇后java算法。(回溯),java,algorithm,recursion,backtracking,n-queens,Java,Algorithm,Recursion,Backtracking,N Queens,有人能给我一个关于java程序的提示或指导吗?我陷入了回溯的想法。这是代码。如果你看一下solve()方法,它会递归地调用自己,但是我被困在一个点上,它无法放置更多的皇后,并试图回溯 public NQueens(int N) { this.N = N; board = new boolean[N][N]; solved = solve(N); if(solved == true) { System.out.println(N+"x"+N+
public NQueens(int N)
{
this.N = N;
board = new boolean[N][N];
solved = solve(N);
if(solved == true)
{
System.out.println(N+"x"+N+" solution:");
printBoard(N);
}
else
{
System.out.println("There is no solution for "+N+"x"+N+" board");
}
}
public boolean solve(int waitingQueens)
{
if(waitingQueens == 0) return true;
for(int row = 0; row < N; row++)
{
for(int column = 0 ; column < N ; column++)
{
if(isValid(row, column))
{
board[row][column] = true;
waitingQueens--;
boolean solved = solve(waitingQueens);
if(!solved)
{
board[row][column] = false;
solved = solve(waitingQueens);
}
return solved;
}
}
}
return false;
}
public boolean isValid(int rowParam, int columnParam)
{
for(int x = 0; x < N; x++)
{
for(int y = 0; y < N; y++)
{
if(board[x][y] == true) //find the already placed queens on the board and check if the queen about to be placed is on a valid position
{
if(x == rowParam) //check the validity of the row
return false;
if(y == columnParam) //check the validity of the column
return false;
if(Math.abs(x-rowParam) == Math.abs(y-columnParam)) //check the validity of the diagonals
return false;
}
}
}
return true;
}
public void printBoard(int printParam)
{
for(int x1 = 0; x1 < printParam; x1++)
{
for(int y1 = 0; y1 < printParam; y1++)
{
if(board[x1][y1] == true)
{
System.out.print("Q ");
}
else{
System.out.print("* ");
}
}
System.out.println();
}
System.out.println();
}
public nqueen(int N)
{
这个,N=N;
board=新布尔值[N][N];
已求解=求解(N);
如果(已解决==真)
{
System.out.println(N+“x”+N+“溶液:”);
印刷电路板(N);
}
其他的
{
System.out.println(“没有针对“+N+”x“+N+”板的解决方案”);
}
}
公共布尔解算(int waitingQueens)
{
if(waitingQueens==0)返回true;
对于(int行=0;行
我推测这就是您试图实现的算法:假设您已经有了M
皇后(看起来像M
=N-waitingqueen
或其他什么)。然后,你寻找每一个可以放置女王的空广场。如果在那里放置皇后是有效的,您可以将board
中的正方形设置为true
,然后递归调用solve
,查看是否可以放置waitingQueens-1
更多皇后
最大的问题在于,如果递归的solve
返回false
,会发生什么情况。假设它是一个4x4板,waitingQueens
是4。您将放置第一个皇后,然后使用waitingQueens=3
调用solve
。但假设它说没有解决办法。然后执行以下操作:
if(!solved)
{
board[row][column] = false;
solved = solve(waitingQueens);
}
这将把方块设置为false
,这意味着电路板现在又空了。但是,然后您使用waitingQueens=3
调用solve(waitingQueens)
,这意味着您的递归solve
现在将寻找板上只有3个皇后的解决方案。这不可能是对的。将waitingQueens
重新递增到4将导致无限递归,因为solve(4)
将使用相同的空板调用solve(4)
这里的问题是,你已经在一个双循环中,将寻找每一个可以放置女王的正方形。如果您试图将皇后放置在某个位置,但没有成功(递归调用失败),则删除皇后,然后让双循环为您找到下一个有效的平方。您不想执行另一个递归调用。因此,应该删除上面的solve(waitingQueens)
调用
此外,还需要解决这一问题:
waitingQueens--;
boolean solved = solve(waitingQueens);
减少waitingQueens
是个坏主意,因为如果solve
返回false
,并且必须返回到下一个循环迭代,waitingQueens
将比以前少一个,这是不好的。您可以通过在if(!solved)
分支中说waitingQueens++
来恢复它,但是为什么要麻烦呢?将waitingQueens
放在一边,将上面的两行替换为
boolean solved = solve(waitingQueens-1);
我不确定这两个修复是否足以产生正确的答案,但它们只是一个开始。我还想提到另外几件事,尽管这些只是优化:(1)你在
solve
中的循环甚至不应该看到不是空的方块。按照您编写的方式,isValid
将返回false
,如果您给它一个不是空的正方形,但它会以迂回的方式返回。我可能会在调用isValid
之前检查方块是否为空。(2) 一旦将M
皇后放置在第0行到M-1
行中,递归调用甚至不应该查看这些行,因为我们知道不能在同一行中有两个皇后。如果您查看第M行,但没有找到解决方案,您可以立即放弃,因为我们知道正确的解决方案必须在每一行都有一个皇后。因此,您实际上只需要在solve
中执行一个循环,我想这就是您试图实现的算法:假设板上已经有M
皇后(看起来像M
=N-waitingQueens
之类)。然后,你寻找每一个可以放置女王的空广场。如果在那里放置皇后是有效的,您可以将board
中的正方形设置为true
,然后递归调用solve
,查看是否可以放置waitingQueens-1
更多皇后