Java 如何在N-Queen问题中跳过重复的电路板状态?
我已经写了一些运行良好的代码,除了它也发现了重复的电路板状态。我希望在代码中进行最小的更改,以便它只能找到唯一的板状态。我正在将代码粘贴到下面:Java 如何在N-Queen问题中跳过重复的电路板状态?,java,algorithm,data-structures,backtracking,n-queens,Java,Algorithm,Data Structures,Backtracking,N Queens,我已经写了一些运行良好的代码,除了它也发现了重复的电路板状态。我希望在代码中进行最小的更改,以便它只能找到唯一的板状态。我正在将代码粘贴到下面: class Solution { List<List<String>> arrangements = new ArrayList<>(); public List<List<String>> solveNQueens(int n) { int
class Solution {
List<List<String>> arrangements = new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
int visited[][] = new int[n][n];
char board[][] = new char[n][n];
solve(board,visited,0);
return arrangements;
}
public boolean solve(char board[][], int visited[][], int queens) {
if(queens == board.length) {
return true;
}
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board.length; j++) {
if(visited[i][j] == 0) {
changePosition(visited,i,j,1); //set
board[i][j] = 'Q';
if(solve(board,visited,queens+1)) {
save(board);
}
changePosition(visited,i,j,-1); // unset
board[i][j] = '.';
}
}
}
return false;
}
public void save(char board[][]) {
List<String> state = new ArrayList<>();
for(int i = 0; i < board.length; i++) {
String row = "";
for(int j = 0; j < board.length; j++) {
if(board[i][j] == 'Q'){
row += 'Q';
}else{
row += '.';
}
}
state.add(row);
}
arrangements.add(state);
}
public void changePosition(int visited[][], int i, int j, int val) {
// setting the column
for(int k = 0; k < visited.length; k++) {
visited[k][j] += val;
}
visited[i][j] -= val;
//setting the row
for(int k = 0; k < visited.length; k++) {
visited[i][k] += val;
}
visited[i][j] -= val;
//setting 1 diagonal
int a = i, b = j;
while(a < visited.length && b < visited.length) {
visited[a][b] += val;
a++;
b++;
}
visited[i][j] -= val;
a = i;
b = j;
while(a >= 0 && b >= 0) {
visited[a][b] += val;
a--;
b--;
}
visited[i][j] -= val;
//setting 2nd diagonal
a = i;
b = j;
while(a < visited.length && b >= 0) {
visited[a][b] += val;
a++;
b--;
}
visited[i][j] -= val;
a = i;
b = j;
while(a >=0 && b < visited.length) {
visited[a][b] += val;
a--;
b++;
}
}
}
类解决方案{
列表排列=新的ArrayList();
公共列表解算器(int n){
已访问的int[][]=新int[n][n];
字符板[][]=新字符[n][n];
求解(单板,已访问,0);
返回安排;
}
公共布尔解算(字符板[],int访问[],int皇后){
if(皇后区==电路板长度){
返回true;
}
对于(int i=0;i=0&&b>=0){
访问[a][b]+=val;
a——;
b--;
}
访问[i][j]=val;
//设置第二对角线
a=i;
b=j;
而(a=0){
访问[a][b]+=val;
a++;
b--;
}
访问[i][j]=val;
a=i;
b=j;
while(a>=0&&b
函数
solveNQueens
以电路板状态的列表
的形式返回所有有效的电路板状态(用字符串
表示的行的列表
中表示的电路板状态)。提前谢谢 您的代码的问题是,对于每个女王,您都会尝试所有可能的董事会位置。这意味着对于n
queen,每个解决方案都将重复n代码>次数(在解决方案中,n
皇后可以在皇后位置之间排列的次数)
我们可以从您的程序为每个n
()找到的解决方案的数量中看出这一点:
n=4
:存在2
解决方案,但您的程序会找到48=2*4!=2*24
解决方案
n=5
:有10
解决方案,但您的程序会找到1200=10*5=10*120
解决方案
n=6
:存在4
解决方案,但您的程序会找到2880=4*6!=4*720
解决方案
这可以很容易地解决:与其为每个皇后尝试所有可能的棋盘位置,不如将每个皇后限制在一个固定的列中,并且只尝试该列中的位置。这样,就不会发现重复的电路板位置
在solve
方法中,删除for
循环的内部,而是将j
坐标设置为皇后的编号(表示皇后0将位于第0列,皇后1将位于第1列,依此类推):
public boolean solve(char board[]],int-visted[]],int-queens){
if(皇后区==电路板长度){
返回true;
}
对于(int i=0;i
public boolean solve(char board[][], int visited[][], int queens) {
if (queens == board.length) {
return true;
}
for (int i = 0; i < board.length; i++) {
int j = queens;
...