我正在尝试编写一个回溯代码,该代码将在NQueens问题中找到解决方案的数量。但是当我试图标记对角线网格时,我发现堆叠溢出是不安全的。“
int dim;
private void recurseMark(int row, int col, boolean[][] board, boolean val) {
if(row >= dim || col >= dim || row < 0 || col < 0) return;
if(board[row][col]) return;
System.out.println("Row " + row + " Col " + col);
board[row][col] = val;
recurseMark(row+1, col-1, board, val);
recurseMark(row+1, col+1, board, val);
recurseMark(row-1, col+1, board, val);
recurseMark(row-1, col-1, board, val);
}
private void mark(int i, int k, boolean[][] board, boolean val) {
for(int j = 0; j < dim; j++) {
board[i][j] = val;
}
for(int j = 0; j < dim; j++) {
board[j][k] = val;
}
}
private int countQueens(int i, boolean[][] board) {
int count = 0;
if(i == dim) return 1;
for(int k = 0; k < dim; k++) {
if(!board[i][k]) {
board[i][k] = true;
mark(i, k, board, true);
System.out.println("Giving " + i + " " + k);
recurseMark(i, k, board, true);
count += countQueens(i+1, board);
recurseMark(i, k, board, false);
mark(i, k, board, false);
}
}
return count;
}
public int totalNQueens(int n) {
dim = n;
boolean[][] board = new boolean[n][n];
return countQueens(0, board);
}
public static void main(String[] args) {
NQueens nq = new NQueens();
System.out.println(nq.totalNQueens(2));
}
知道为什么它会因为N的小值而溢出?
答案 0 :(得分:1)
因为你的方法无限地递归。
如果电路板是8x8,那么例如recurseMark(1, 1, board, false)
拨打recurseMark(2, 2, board, false)
,呼叫recurseMark(1, 1, board, false)
,呼叫recurseMark(2, 2, board, false)
,呼叫recurseMark(1, 1, board, false)
......
答案 1 :(得分:1)
问题是当使用false调用recurseMark时。这是一个正确的recurseMark():
private void recurseMark(int row, int col, Boolean[][] board, Boolean val) {
if(row >= dim || col >= dim || row < 0 || col < 0) return;
if(board[row][col] != null) return;
System.out.println("Row " + row + " Col " + col);
board[row][col] = val;
recurseMark(row+1, col-1, board, val);
recurseMark(row+1, col+1, board, val);
recurseMark(row-1, col+1, board, val);
recurseMark(row-1, col-1, board, val);
}
我们在这里做的是切换到布尔类而不是原始布尔值,并使用空案例来表示未被访问过的&#34; square&#34;。因为它没有被访问的&#34;广场&#34;国家是&#34;假&#34;。