51. N-Queens

 N-Queens(n皇后)

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.

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皇后问题很经典,以前上算法课的时候,老师曾仔细讲过。照着以前书上的讲解实现了一下
这里的约束条件是:任何两个皇后都不能位于同一条对角线上,也不能在同一直线上。这里安排第k个皇后放在第k行,我们要做的是找到它放在第k行的哪一列。
这里定义一个全局的变量vector<int> X,X[k]代表第k个皇后放在第k行的第X[k]列。不能在同一对角线上的表达式abs(i-k)!=abs(X[i]-X[k]),不能在同一
直线上的表达是X[i]!=X[k].这里约束条件可以用一个bool函数Place表述。进入此过程时,已经设置好了k-1个皇后的位置,此时检验第k个皇后的位置X[k]
是否与前k-1个位置有冲突。
有了place函数后,用回溯解决n皇后问题。如下所示,其中print函数将一个可行解表达出来。

class Solution {
    vector
     
     
      
       X;
    //如果第k个皇后能放在第X[k]列,则返回true.X是一个全程数组,进入此过程时,已经设置了k-1个值,检验第k个皇后的位置X[k]
    //是否与前k-1个皇后的位置有冲突
    bool Place(int k)
    {
        int i=0;
        while(i
      
      
       
        print(vector
       
       
        
         X)
    {
       
        int n=X.size();
         vector
        
        
         
          r(n);
         string s;
        for(int i=0;i
         
         
           > solveNQueens(int n) { X.resize(n); vector 
           
           
             > sr; int k; X[0]=-1;k=0;//k是当前行,从第0列开始,所以初始时设为-1,因为有X[k]=X[k]+1; while(k>=0) { X[k]=X[k]+1;//转到下一列 while(X[k] 
            
              s; s=print(X); sr.push_back(s); }else { k++;//转到下一行 X[k]=-1; } } else//所有列都不行,回溯 k--; } return sr; } }; 
             
            
           
         
        
        
       
       
      
      
     
     

//update: 2017.5.29

递归的方法

class Solution {
    vector<vector<string>> ans;
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<string> ss(n,string(n,'.'));
        dfs(0,n,ss);
        return ans;
    }
    void dfs(int row,int n,vector<string> &ss)
    {
        if(row>=n)
        {
            ans.push_back(ss);
            return;
        }else{
            for(int col=0;col<n;col++)
            {
                if(ok(ss,row,col,n))
                {
                    ss[row][col]='Q';
                    dfs(row+1,n,ss);
                    ss[row][col]='.';//重置
                }
            }
        }
    }
    bool ok(vector<string> & ss,int row,int col,int n)
    {
        int i,j;
        //1.检查竖
        for(int i=0;i<row;i++)
        if(ss[i][col]=='Q')
        return false;
        
        //2.检查正对角线
        i=row-1;j=col-1;
        while(i>=0&&j>=0)
        {
            if(ss[i--][j--]=='Q')
            return false;
        }
        
        //3.检查斜对角线
        i=row-1;j=col+1;
        while(i>=0&&j<n)
        {
            if(ss[i--][j++]=='Q')
            return false;
        }
        return true;
    }

};


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值