zhizhizhiyuan

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;
    }
};

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

  

posted on 2014-07-12 23:16  zhizhizhiyuan  阅读(185)  评论(0编辑  收藏  举报

导航