题意分析

  • 经典模板题,n皇后问题。给你一张nxn的棋盘。需要往这个棋盘里面放一些棋子。然后需要保证这n个棋子之间不同同行同列和同正反斜线。

  • 也就是下图中在同一条线上面的不能同时放置棋子。

图片说明

思路分析

  • 好了,我们现在知道题目意思了,我们可以来说说怎么解这题。首先,我们需要知道如何判断两个位置是否满足题目条件。同一行同一列我们知道可以可以使用两个数组来标识。但是如何处理正对角线和反对角线的情况呢?我们根据上面的图可以知道,对于正和反对角线的情况。这两种线的斜率分别为1和-1.假设有两个点在正斜线上,那么,反斜线同理。所以我们可以将每个点放入一个数组里面。但是对于正斜线的情况,我们发现可能存在负数的情况,为了防止负数的产生,我们可以给这个和加上一个n保证这个数为正数。

  • 知道怎么判断之后,我们来说一下怎么遍历所有的情况,那就是回溯算法。我们对这个棋盘进行dfs,我们以x坐标作为dfs的起点,一层一层向下进行递归处理,当我们到了某一层的时候,我们枚举这一层放置的位置的y坐标,如果满足条件,则向下进行递归,然后进行回溯即可。

  • DFS回溯的话可以结合我的这张图进行理解。
    图片说明

写法一 C++版

  • 代码如下
    • 我们需要枚举出n个棋子的所有的排列。所以空间复杂度为O(n!)
    • bool数组需要存储坐标的和,最大需要开到2n,所以空间复杂度为O(n)
class Solution {
public:
    /**
     * 
     * @param n int整型 the n
     * @return int整型
     */
    bool col[16],row[16],pos[30],neg[30];
    int ans=0;
    void dfs(int x,int n){ // x表示此时的横坐标的位置
      //  std::cout<<x<<endl;
        if(x==n+1){
            // 可以成功到达边界,答案累加1
            ans++;
            return;
        }
        for(int i=1;i<=n;i++){  // 枚举纵坐标
            // 如果选的这个位置在同一行,同一列,同一正斜线和同一反斜线,那么就不符合
            //std::cout<<col[i]<<row[x]<<pos[i-x+n]<<neg[i+x]<<endl;
            if(col[i]||row[x]||pos[i-x+n]||neg[i+x]) continue;
            // 此时在(x,i)位置放一个皇后
            col[i]=row[x]=pos[i-x+n]=neg[i+x]=true;
            dfs(x+1,n);
            // 进行回溯
            col[i]=row[x]=pos[i-x+n]=neg[i+x]=false;
        }
    }
    int Nqueen(int n) {
        // write code here
        memset(pos,false,sizeof(pos));
        memset(neg,false,sizeof(neg));
        memset(row,false,sizeof(row));
        memset(col,false,sizeof(col));
        dfs(1,n);
        return ans;
    }
};

写法二 Go语言版

  • 代码如下
    • 我们需要枚举出n个棋子的所有的排列。所以空间复杂度为O(n!)
    • bool数组需要存储坐标的和,最大需要开到2n,所以空间复杂度为O(n)
package main

/**
 * 
 * @param n int整型 the n
 * @return int整型
*/

var ans int

func dfs(x, n int,col,row,neg,pos []bool){
    if(x==n){ // x表示此时的横坐标的位置
        ans+=1
        return
    }
    for i:= 1;i<=n;i++ { // 枚举纵坐标
        // 如果选的这个位置在同一行,同一列,同一正斜线和同一反斜线,那么就不符合
        if(col[i]||row[x]||pos[i-x+n]||neg[i+x]) {
            continue
        }else{
            col[i]=true
            row[x]=true
            pos[i-x+n]=true
            neg[i+x]=true
            // 此时在(x,i)位置放一个皇后
            dfs(x+1,n,col,row,neg,pos)
            // 进行回溯
            col[i]=false
            row[x]=false
            pos[i-x+n]=false
            neg[i+x]=false
        }
    }
}
func Nqueen( n int ) int {
    // write code here
    row := make([]bool,n+1)
    col := make([]bool,n+1)
    pos := make([]bool,2*n+1)
    neg := make([]bool,2*n+1)
    dfs(0,n,col,row,neg,pos)
    return ans;
}