给定一个皇后固定在某个列上,如何找到 NQueens 问题的所有解决方案?

Posted

技术标签:

【中文标题】给定一个皇后固定在某个列上,如何找到 NQueens 问题的所有解决方案?【英文标题】:How to find all the solutions for a NQueens problem given that one queen is fixed at some column? 【发布时间】:2021-06-19 16:31:51 【问题描述】:

这就是著名的 NQueens 问题。我的程序运行良好(回溯方法)。它可以找到给定电路板尺寸的所有解决方案。 代码如下所示。

我正在尝试修改代码,以便我可以找到第一个皇后的给定列的所有解决方案。我不想更改第一个皇后的位置。例如,它将为我提供解决方案

  [2, 0, 3, 1, 4] and [2, 4, 1, 3, 0]

当我将第一个皇后设置为 2 时,棋盘大小为 5(第三列,索引从零开始)。

我通过为 k(以及 board[k] )设置不同的值来尝试这个,但并没有完全达到目标。 任何提示将不胜感激。

这是我的代码。删除了有关 place 方法的详细信息,因为不应更改它以实现我的新目标。

public class NQueensAllSolutions

    //  Board size
    static int size = 8;
    
    //  One dimensional array to store the column number for all queens.
    static int[] board = new int[size];
    
    //  This method will check the validity for a new queen. works fine.
    static boolean place(int k)
    
        .
        .       
    
    
    
    public static void main(String[] args) 
    
        int k;
        
        long t=0;   //  for counting total found solutions

        k = 0;
        board[k] = -1;      

        while(k >= 0) 

            board[k]++;

            while(board[k] < size && !(place(k))) board[k]++;

            if(board[k] < size) 
                if(k == size-1)    //  a solution is found.
                    
                    t++;                    
                    
                    //System.out.println("\n\nTotal: "+t+" --> "+Arrays.toString(board));   
                
                else 
                    k++; board[k] = -1;
                
            
            else               
                k--;    //  backtrack.              
            
        
        
        System.out.println("\n\nTotal: "+t);
    

【问题讨论】:

有趣!你在玩 k 和 board[k] 值时尝试过调试吗? 5 号板的输出显示? 是的,板尺寸 5。我将把它放在我的问题描述中。 【参考方案1】:

while循环中保持k大于0:

import java.util.Arrays;

public class Queens

    static int size = 5;
    static int[] board = new int[size];

    static boolean isValid(int k)
    
        int c1 = board[k];
        int c2 = board[k];
        for(int r=k-1;r>=0;r--)
        
            c1--;
            c2++;
            if(board[r] == board[k] || board[r] == c1 || board[r] == c2)
                return false;
        
        return true;
    

    public static void main(String[] args) 
    
        int t = 0;

        // Set the first queen position
        board[0] = 2;

        int k = 1;
        board[k] = -1;

        // k must stay greater than 0
        while(k >= 1) 
            board[k]++;
            while(board[k] < size && !isValid(k))
                board[k]++;
            if(board[k] < size) 
                if(k == size-1) 
                    t++;
                    System.out.println("Solution "+t+" --> "+Arrays.toString(board));
                
                else 
                    k++;
                    board[k] = -1;
                
            
            else 
                k--;
            
        
    

输出:

Solution 1 --> [2, 0, 3, 1, 4]
Solution 2 --> [2, 4, 1, 3, 0]

更新

这是一个通用版本,可以在位置(fixedRowfixedCol)强制女王。 关键变化是新的getNextCol() 方法,它用于获取下一个可能的皇后列。在行fixedRow 上,唯一可能的列是fixedCol。在其他行上,所有列都是可能的。

import java.util.Arrays;

public class Queens

    static int size = 5;
    static int fixedRow = 2;
    static int fixedCol = 0;
    static int[] board = new int[size];

    static boolean isValid(int k)
    
        int c1 = board[k];
        int c2 = board[k];
        for(int r=k-1;r>=0;r--)
        
            c1--;
            c2++;
            if(board[r] == board[k] || board[r] == c1 || board[r] == c2)
                return false;
        
        return true;
    

    static int getNextCol(int k, int col)
    
        if(k == fixedRow) 
            // Only one possible move on this row
            return col == -1 ? fixedCol : size;
        
        else 
            // Try the next column
            return col+1;
        
    

    public static void main(String[] args) 
    
        int t = 0;
        int k = 0;
        board[k] = -1;

        while(k >= 0) 
            board[k] = getNextCol(k, board[k]);
            while(board[k] < size && !isValid(k))
                board[k] = getNextCol(k, board[k]);
            if(board[k] < size) 
                if(k == size-1) 
                    t++;
                    System.out.println("Solution "+t+" --> "+Arrays.toString(board));
                
                else 
                    k++;
                    board[k] = -1;
                
            
            else 
                k--;
            
        
    

输出:

Solution 1 --> [1, 3, 0, 2, 4]
Solution 2 --> [4, 2, 0, 3, 1]

【讨论】:

我离那里很近!谢谢,能帮我个忙吗?我还需要做什么才能将其应用于其他皇后区?假设我想将任何皇后(只有一个)修复到任何列。 @奥利维尔。

以上是关于给定一个皇后固定在某个列上,如何找到 NQueens 问题的所有解决方案?的主要内容,如果未能解决你的问题,请参考以下文章

N皇后(算法)通过数组不理解几行

SQL:根据另一列的值在列上保留一个具有最大值的行

N皇后问题—初级回溯

leetcode第一刷_N-Queens

python学习八皇后问题

LeetCode第五十一题-N皇后