提问人:Vivek Kumar 提问时间:9/15/2021 更新时间:9/15/2021 访问量:298
将 N Queen 问题的所有解添加到数组列表中
Adding all solutions of N Queen Problem to an arrayList
问:
n-queens 谜题是将 n 个皇后放在 (n×n) 棋盘上的问题,这样两个皇后就不能互相攻击。
我使用回溯来解决问题。但是我遇到了一个奇怪的问题。
下面是我写的代码:
import java.util.ArrayList;
public class NQueenProblem {
static ArrayList<ArrayList<Integer>> ans = new ArrayList<ArrayList<Integer>>();
static ArrayList<ArrayList<Integer>> nQueen(int n) {
ArrayList<Integer> positions = new ArrayList<Integer>();
//boolean[][] placed = new boolean[n][n];
solveNQueenRec(n, 0, new boolean[n][n], positions);
//for dubugging purpose. This prints empty arrays. not able to understand why?
for (ArrayList<Integer> list : ans)
System.out.println(list);
return ans;
}
static void solveNQueenRec(int n, int col, boolean[][] placed, ArrayList<Integer> positions) {
if (col == n) {
//for debugging process
System.out.println("Adding " + positions);
ans.add(positions);
System.out.println("Added " + positions);
}
for (int row = 0; row < n && col < n; row++) {
if (isSafe(row, col, placed, n)) {
placed[row][col] = true;
positions.add(row + 1);
solveNQueenRec(n, col + 1, placed, positions);
placed[row][col] = false;
positions.remove(positions.size() - 1);
}
}
// return null;
}
private static boolean isSafe(int row, int col, boolean[][] placed, int n) {
boolean safe = true;
// checking if exists in same row
for (int i = 0; i < col; i++) {
if (placed[row][i])
safe = false;
}
// checking for upper diagonal
for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
if (placed[i][j])
safe = false;
}
// checking for lower diagonal
for (int i = row, j = col; i < n && j >= 0; i++, j--) {
if (placed[i][j])
safe = false;
}
return safe;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
nQueen(4);
}
}
我无法理解的是,当我在日志列表中看到被添加到我的 ans 时,为什么我的 ans 是空的。 我是在犯什么愚蠢的错误。请帮我解决这个问题。如果可能的话,请帮助我提供链接以了解该问题以及我将来如何避免这些问题。
答:
-1赞
chanrlc
9/15/2021
#1
添加此检查,确保它大于零,然后打印出答案。此外,添加打印女王功能,您将清楚地看到答案。如果这解决了您的问题,请作为答案。
for (ArrayList<Integer> list : ans) {
if (list.size() > 0)
System.out.println(list);
}
static void solveNQueenRec(int n, int col, boolean[][] placed, ArrayList<Integer> positions) {
if (col == n)
printQueens(positions);
for (int row = 0; row < n && col < n; row++) {
if (isSafe(row, col, placed, n)) {
placed[row][col] = true;
positions.add(row + 1);
solveNQueenRec(n, col + 1, placed, positions);
placed[row][col] = false;
positions.remove(positions.size() - 1);
}
}
// return null;
}
public static void printQueens(ArrayList<Integer> q) {
int n = q.size();
for (int i = 0; i < n; i++) {
for (int j = 1; j <= n; j++) {
if (q.get(i) == j)
System.out.print("Q ");
else
System.out.print("* ");
}
System.out.println();
}
System.out.println();
}
solution to 4-queens sample:
* Q * *
* * * Q
Q * * *
* * Q *
* * Q *
Q * * *
* * * Q
* Q * *
评论
0赞
tgdavies
9/15/2021
这根本不是OP的问题。
0赞
chanrlc
9/15/2021
修改代码后,答案将是正确的: 添加 [2, 4, 1, 3] 添加 [2, 4, 1, 3] 添加 [3, 1, 4, 2] 添加 [3, 1, 4, 2]
0赞
tgdavies
9/15/2021
“我无法理解的是,当我在日志列表中看到被添加到我的 ans 中时,为什么我的 ans 是空的” 这是 OPs 问题,您还没有回答。
0赞
chanrlc
9/15/2021
因为没有打印出来的解决方案。
0赞
chanrlc
9/15/2021
尝试在黑板上打印皇后。不要添加到 ans 列表。由于 4-queens 只有两个解决方案,并且列表大小为 4,因此将返回两个空列表 []。我清楚吗?
2赞
tgdavies
9/15/2021
#2
我想你相信当 JVM 执行时
ans.add(positions);
它正在获取当前状态的副本并将其添加到列表中。它不是,它正在做代码所说的:添加对 .positions
ArrayList
ans
中的所有项目都是对相同的引用,并且当您打印出来时,该数组列表是空的。ans
ArrayList
ans
1赞
Jean-Baptiste Yunès
9/15/2021
#3
ans.add(positions);
是你的“问题”。您只是添加到对列表的引用中。因此充满了对同一列表的引用。当您在插入后多次修改时,直到清空它,最后充满了 n 个引用(n 是找到的解决方案的数量)与末尾为空的相同列表。ans
positions
ans
positions
positions
ans
positions
您需要在找到解决方案时插入当前列表的副本:positions
ans.add(new ArrayList<Integer>(positions));
副本是通过构建具有原始列表确切内容的新列表来获得的。
评论
positions