LeetCode OJ 之 N-Queens(N皇后)

来源:互联网 发布:航路查询软件 编辑:程序博客网 时间:2024/06/05 17:11

题目:

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

Given an integer n, return all distinct solutions to the n-queens puzzle.

Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.

N皇后问题是在一个n x n 的棋盘上放置N个皇后,使得每个皇后不同行、不同列也不能在同一条斜线上。

给定一个整数n,返回所有不同的可能性。每个结果包含不同的设置,放置Q和 . 分别代表一个皇后和空格。

For example,
There exist two distinct solutions to the 4-queens puzzle:

[ [".Q..",  // Solution 1  "...Q",  "Q...",  "..Q."], ["..Q.",  // Solution 2  "Q...",  "...Q",  ".Q.."]]

思路:

1、这里可以用数组vector<int> q(n,0),q[i]表示第 i 行的queen放在 q[i] 列,这样就转化成求0~n-1总共 n 个数的全排列,全排列可以参考:http://blog.csdn.net/u012243115/article/details/42965749 。然后对这n! 个全排列进行筛选,这个全排列保证了棋盘图的每个皇后的行列不同,还要判断每个皇后的位置不在一条斜线上,详情见代码。

2、依次放置每行的皇后。在放置的时候,要保持当前的状态为合法,即与上面行的皇后不冲突,即当前放置位置的同一行、同一列、同一斜线线上都不存在皇后。

3、结合上面两种方法。

代码1:

class Solution {public:    vector<vector<string> > solveNQueens(int n)    {        vector<vector<string> > result;//保存结果        vector<int> q(n,0);//q[i]表示棋盘上第i行的'Q'位于q[i]列,下面的for循环初始化使得每个'Q'位于不同行不同列        for(int i = 0 ; i < n ; i++)    //初始化q        {            q[i] = i;        }        DFS(n,0,q,result);//调用DFS构造棋盘图        return result;    }    void DFS(int n , int start , vector<int> &q , vector<vector<string> > &result)    {        if(start == n)        {            //筛选全排列            for(int i = 0 ; i < n ; i++)            {                for(int j = i + 1 ; j < n ; j++)                {                    if((j-i) == abs(q[j]-q[i])) //如果两个皇后在一条斜线上,则此种排列不符合条件,直接返回                    {                        return;                    }                }            }            //如果没有被筛选掉,则构造棋盘图            vector<string> cur(n,string(n,'.'));//先构造一个全部为'.'的图,然后再设置皇后的位置            for(int i = 0 ; i < n ; i++)            {                cur[i][q[i]] = 'Q';//把第i行,第q[i]列的元素设置为皇后            }            result.push_back(cur);            return;        }        for(int i = start ; i < n ; i++)        {            swap(q[i],q[start]);            DFS(n,start+1,q,result);//递归求全排列            swap(q[i],q[start]);        }    }};

代码2:

class Solution {private:    vector<vector<string> > result;public:    vector<vector<string> > solveNQueens(int n)     {        vector<string> cur(n, string(n,'.'));        DFS(cur, 0);        return result;    }    void DFS(vector<string> &cur, int row)    {        if(row == cur.size())        {            result.push_back(cur);            return;        }        for(int col = 0; col < cur.size(); col++)        {            if(isValid(cur, row, col))            {                cur[row][col] = 'Q';//在当前位置放置皇后之前检查是否与上面的皇后冲突,不冲突后才能放置                DFS(cur, row+1);//递归调用下一行                cur[row][col] = '.';//恢复当前位置            }        }    }    //判断在cur[row][col]位置放一个皇后,是否是合法的位置    //已经保证了每行一个皇后,只需要判断列是否合法以及对角线是否合法。    bool isValid(vector<string> &cur, int row, int col)    {        //列        for(int i = 0; i < row; i++)        {            if(cur[i][col] == 'Q')                return false;        }        //左上角对角线(只需要判断对角线上半部分,因为后面的行还没有开始放置)        for(int i = row-1, j=col-1; i >= 0 && j >= 0; i--,j--)        {            if(cur[i][j] == 'Q')                return false;        }        //右上角对角线(只需要判断对角线上半部分,因为后面的行还没有开始放置)        for(int i = row-1, j=col+1; i >= 0 && j < cur.size(); i--,j++)        {            if(cur[i][j] == 'Q')                return false;        }        return true;    }};

代码3:

class Solution {private:    vector<vector<string> > result;public:    vector<vector<string> > solveNQueens(int n)     {        vector<int> q(n,-1);        DFS(n,q, 0);        return result;    }    void DFS(int n , vector<int> &q, int row)    {        if(row == n)        {            vector<string> cur(n,string(n,'.'));            for(int i = 0 ; i < n ; i++)            {                cur[i][q[i]] = 'Q';            }            result.push_back(cur);            return;        }        for(int col = 0; col < n; col++)        {            if(isValid(q, row, col))            {                q[row] = col;//在当前位置放置皇后之前检查是否与上面的皇后冲突,不冲突后才能放置                DFS(n,q,row+1);//递归调用下一行                q[row] = -1;//恢复当前位置            }        }    }    bool isValid(vector<int> q, int row, int col)    {        for(int i = 0 ; i < row ; i++)        {            if(q[i] == col || (row - i) == abs(col - q[i]))                return false;        }        return true;    }};



0 0