zoukankan      html  css  js  c++  java
  • N-Queens

      N皇后问题,经典中的经典。

      第一遍的时候,只有点思路,但是想不清楚,看了别人的代码。

      方法一(Java): 

    public class Solution {
        int[] row;
        int[] col;
        ArrayList<String[]> res;
        int N;
    
        public void dfs(int r)
        {
            int j;
            if(r==N)
            {
                String[] sa=getBoard();
                res.add(sa);
                return;
            }
            for(int i=0;i<N;i++)
            {
                if(col[i]==0)
                {
                    for(j=0;j<r;++j)
                    {
                        if(Math.abs(j-r)==Math.abs(i-row[j]))
                            break;
                    }
                    if(j==r)
                    {
                        row[r]=i;
                        col[i]=1;
                        dfs(r+1);
                        col[i]=0;
                        row[r]=0;
                    }
                }
            }
    
        }
    
        public String[] getBoard()
        {
            char[] ca=new char[N];
            Arrays.fill(ca,'.');
            String line;
            String[] ret=new String[N];
            for(int i=0;i<N;i++)
            {
                ca[row[i]]='Q';
                line=new String(ca);
                ca[row[i]]='.';
                ret[i]=line;
            }
            return ret;
        }
    
        public ArrayList<String[]> solveNQueens(int n)
        {
            N=n;
            row=new int[n];
            col=new int[n];
            res=new ArrayList<String[]>();
            dfs(0);
            return res;
        }
    }

      基本思想是dfs,深度就是行数。对于每一层,从左到右依次在可以放的位置放上皇后。用一个行数组和一个列数组来记录当前哪些行、哪些列是放了皇后的:列数组记录当前列是否放了皇后,行数组用于记录当前行的哪一列是放了皇后的。能否放皇后由一个单独的判断函数来执行。这就是典型的dfs+判断函数模式。判断函数借助于行数组和列数组可以非常简单:

      方法二(c++):

    class Solution {
    public:
        int N;
        vector<string> *pBoard;
        vector<vector<string>> res;
    
        vector<vector<string> > solveNQueens(int n) {
            N=n;
            vector<string> board(N,string(N,'.'));
            pBoard=&board;
            solve(0);
            return res;
        }
    
        void solve(int r)
        {
            if(r==N)
            {
                addSolution();
                return;
            }
            for(int c=0;c<N;c++)
            {
                if(canPlace(r,c))
                {
                    (*pBoard)[r][c]='Q'; 
                    solve(r+1);
                    (*pBoard)[r][c]='.';
                }
            }
        }
    
        void addSolution(){
            res.push_back(*pBoard);
        }
    
        bool canPlace(int r,int c)
        {
            for(int i=0;i<r;i++)
            {
                if((*pBoard)[i][c]=='Q'||
                   (c+r-i<N&&(*pBoard)[i][c+r-i]=='Q')||
                   (c-(r-i)>=0&&(*pBoard)[i][c-(r-i)]=='Q'))
                    return false;
            }
            return true;
        }
    };

      第二遍的时候,完全没有意识要另外借助两个数组来记录放置位置。事实上是没有这个必要,因为我们一直都在维护这个棋盘,所有的信息都可以从棋盘中获得,因此判断函数也可以直接对棋盘进行分析而来。这种方式其实是更容易想到的,只是判断函数的条件确实要费一番周折。

      

  • 相关阅读:
    Pieczęć(模拟)
    【并查集】关押罪犯
    火车进栈
    独木舟上的旅行
    哈尔滨理工大学第八届程序设计团队赛K题
    [数学、递推]Everything Is Generated In Equal Probability
    [构造]triples I
    2019牛客第三场
    [DP]销售
    [哈夫曼树]猜球球
  • 原文地址:https://www.cnblogs.com/zhizhizhiyuan/p/3840577.html
Copyright © 2011-2022 走看看