LeetCode--n-queens

题目描述


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 then-queens' placement, where'Q'and'.'both indicate a queen and an empty space respectively.

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

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

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

方法一:递归法

把棋盘存储为一个N维数组a[N],数组中第i个元素的值代表第i行的皇后位置,这样便可以把问题的空间规模压缩为一维O(N),在判断是否冲突时也很简单,首先每行只有一个皇后,且在数组中只占据一个元素的位置,行冲突就不存在了,其次是列冲突,判断一下是否有a[i]与当前要放置皇后的列j相等即可。至于斜线冲突,通过观察可以发现所有在斜线上冲突的皇后的位置都有规律即它们所在的行列互减的绝对值相等,即| row – i | = | col – a[i] | 。这样某个位置是否可以放置皇后的问题已经解决。

class Solution {
public:
    /*方法一、递归实现*/  
    vector<vector<string> > solveNQueens(int n) {  
        // write your code here  
        vector<vector<string>> solutions;  
        /*用一维数组存储*/  
        vector<int> queue(n, -1);  
        /*用一维数组存储*/  
        recursiveFun(solutions, queue, n, 0);  
        return solutions;  
    }  
  
    /*递归实现*/  
    void recursiveFun(vector<vector<string>> &solutions, vector<int> &queue, int n, int row)  
    {  
        if (row >= n)  
        {  
            vector<string> ret = getResult(queue);  
            solutions.push_back(ret);  
        }//if  
        else{  
            for (int j = 0; j < n; ++j)  
            {  
                /*递归在上一个任务成功后*/  
                if (isValid(queue, row, j))  
                {  
                    queue[row] = j;  
                    recursiveFun(solutions, queue, n, row + 1);  
                }//if  
            }//else  
        }//else  
    }
    
        /*判断在r行c列放置皇后,是否合法*/  
    bool isValid(vector<int> queue, int r, int c)  
    {  
        if (queue.empty())  
            return true;  
        for (int i = 0; i < r; ++i)  
        {         
            if (queue[i] == c || abs(i - r) == abs(queue[i] - c))  
                return false;  
        }//for  
        return true;  
    }  
  
    /*将符合要求的结果用字符串数组表示*/  
    vector<string> getResult(vector<int> queue)  
    {  
        if (queue.empty())  
        {  
            return vector<string>();  
        }  
  
        int len = queue.size();  
        vector<string> ret(len, string(len,'.'));  
        for (int i = 0; i < len; ++i)  
        {  
            ret[i][queue[i]] = 'Q';  
        }//for  
        return ret;  
    }  
};


方法二:非递归

非递归方法的一个重要问题时何时回溯及如何回溯的问题。程序首先对N行中的每一行进行探测,寻找该行中可以放置皇后的位置,具体方法是对该行的每一列进行探测,看是否可以放置皇后,如果可以,则在该列放置一个皇后,然后继续探测下一行的皇后位置。如果已经探测完所有的列都没有找到可以放置皇后的列,此时就应该回溯,把上一行皇后的位置往后移一列,如果上一行皇后移动后也找不到位置,则继续回溯直至某一行找到皇后的位置或回溯到第一行,如果第一行皇后也无法找到可以放置皇后的位置,则说明已经找到所有的解程序终止。如果该行已经是最后一行,则探测完该行后,如果找到放置皇后的位置,则说明找到一个结果,打印出来。但是此时并不能再此处结束程序,因为我们要找的是所有N皇后问题所有的解,此时应该清除该行的皇后,从当前放置皇后列数的下一列继续探测。

class Solution {
public:
    /*方法二、非递归实现*/  
    vector<vector<string> > solveNQueens(int n) {  
        // write your code here  
        vector<vector<string>> solutions;  
        /*用一维数组存储*/  
        vector<int> queue(n, -1);  
        int i = 0, j = 0;  
        while(i < n)  
        {  
            while(j < n)  
            {  
                if (isValid(queue, i, j))  
                {  
                    /*第i行的皇后的列为j*/  
                    queue[i] = j;  
  
                    /*继续探测下一个皇后的位置*/  
                    j = 0;  
                    break;  
                }//if  
                else{  
                    ++j;  
                }//else  
            }//while  
  
            /*第i行没有找到可以放置皇后的位置,说明该方案不可行*/  
            if (-1 == queue[i])  
            {  
                /*当前没有可行解的行标为0,说明已经找完所有的解*/  
                if (0 == i)  
                {  
                    break;  
                }//if  
                /*回溯到上一行*/  
                else  
                {  
                    --i;  
                    /*改变上一行皇后的位置*/  
                    j = queue[i] + 1;  
                    queue[i] = -1;    
                    continue;  
                }//else  
            }//if  
  
            /*找到一个可行解*/  
            if (i == n - 1)  
            {  
                vector<string> ret = getResult(queue);  
                solutions.push_back(ret);  
  
                /*不能在此处结束程序,因为我们要找的是N皇后问题的所有解,此时应该清除该行的皇后, 
                从当前放置皇后列数的下一列继续探测。*/  
                j = queue[i] + 1;  
                queue[i] = -1;  
                continue;  
            }//if  
            ++i;  
        }//while  
        return solutions;  
    }  
  
  
    /*判断在r行c列放置皇后,是否合法*/  
    bool isValid(vector<int> queue, int r, int c)  
    {  
        if (queue.empty())  
            return true;  
        for (int i = 0; i < r; ++i)  
        {         
            if (queue[i] == c || abs(i - r) == abs(queue[i] - c))  
                return false;  
        }//for  
        return true;  
    }  
  
    /*将符合要求的结果用字符串数组表示*/  
    vector<string> getResult(vector<int> queue)  
    {  
        if (queue.empty())  
        {  
            return vector<string>();  
        }  
  
        int len = queue.size();  
        vector<string> ret(len, string(len,'.'));  
        for (int i = 0; i < len; ++i)  
        {  
            ret[i][queue[i]] = 'Q';  
        }//for  
        return ret;  
    }  
};



转自: http://blog.csdn.net/fly_yr/article/details/51135059



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值