用全排列方法解决N皇后问题(Leetcode 51)

有关全排列(Permutation)的思路和代码参见前一篇文章:
http://blog.csdn.net/bcj296050240/article/details/51107056

这里叙述一下N皇后问题的解决思路:
规则
N皇后在一个N*N的棋盘上,使其不能相互攻击,即任意两个皇后不得处于同一行,同一列或一条对角线上。

解决方法
由于N个皇后的任意两个不能处在同一行,那么肯定是每个皇后占据一行,于是我们定义一个数组,长度为N。数组的第i个数字代表位于第i行的皇后的列号。先把数组中的N个数字用(0——N-1)初始化,然后对该数组中的数字作全排列。
因为我们是用不同的数字初始化数组,故而所有皇后肯定不同列。因此我们只需要判断每一个排列对应的N个皇后是否在同一条对角线上,也就是对于数组的两个下标i和j,是不是有 abs(A[i]-A[j]) = abs(i - j)。如果成立,则该解法不满足条件。筛选过后可以得到所有满足条件的解法。

具体代码如下:

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> sol;
        vector<vector<int>> res;
        vector<int> arr;
        int end = n-1;
        int start = 0;
        for(int i = 0;i < n;++i)
            arr.push_back(i);
        Permutation(res, arr, start, end);
        convertSol(res, sol);
        return sol;
    }

    void convertSol(vector<vector<int>> &res, vector<vector<string>> &sol){
        for(int i = 0;i < res.size();++i){
            vector<string> vec;
            for(int j = 0;j < res[i].size();++j){
                int pos = res[i][j];
                int k = 0;
                string str;
                while(k < pos){
                    str += ".";
                    ++k;
                }
                str += "Q";
                ++k;
                while(k < res[i].size()){
                    str += '.';
                    ++k;
                }
                vec.push_back(str);
            }
            sol.push_back(vec);
         }
    }

    void Permutation(vector<vector<int>> &res, vector<int> &arr, int start, int end){
        if(start == end){
            bool flag = true;
            for(int i = 0;i < end;++i){
                for(int j = 0;j <= end;++j){
                    if(i != j && (abs(arr[i] - arr[j]) == abs(i-j))){
                        flag = false;
                        break;
                    }//if
                }//for
                if(!flag)
                    break;
            }//for
            if(flag)
                res.push_back(arr);
        }

        for(int i = start;i <= end;i++){
            swap(arr[i], arr[start]);
            Permutation(res, arr, start+1, end);
            swap(arr[i], arr[start]);
        }
    }

};

int main(){
    Solution sul;
    int n = 6;
    vector<vector<string>> res = sul.solveNQueens(n);
    for(int i = 0;i < res.size();++i){
        cout<<"------------"<<endl;
        for(int j = 0;j < res[i].size();++j)
            cout<<res[i][j]<<endl;
        cout<<endl;
    }

    getchar();
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值