八皇后(回溯法)

Posted yc-l

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了八皇后(回溯法)相关的知识,希望对你有一定的参考价值。

题目内容

  • n*n的矩阵,作为棋盘,放置n个皇后,且它们都无法攻击其他皇后,求出放置方法
  • 皇后的攻击方式,沿行、列、对角线都可以攻击其它皇后

基本思想

使用回溯法(穷举法)

所有的回溯问题都是由三个步骤组成:choose、explore、unchoose

因此对每个问题需要知道:

  1.     choose what?   对于这个问题,我们选择每个字符串
  2.     how to explore?对于这个问题,我们对剩余的字符串做同样的事情。
  3.     unchoose           做相反的操作选择

回溯法步骤

1.Define helper(),通常我们需要在回溯问题中使用辅助函数,以接收更多参数

2.parameters:通常我们需要以下参数:

    (1)要处理的对象

    (2)指示正在处理的部分

    (3)阶段性步骤结果,记住当前选择choose然后取消选择unchoose

    (4)最终的结果,记住最终的结果

3.Base case:基本案例。定义何时将步骤结果添加到最终结果中以及何时返回

4.Use for-loop:通常需要一个for循环迭代输入,以便我们可以选择所有选项

5.Choose:在这个问题中,如果s的子串是回文,我们将它添加到步骤中

6.Explore:在这个问题中,我们想对剩余的内容做同样的事情,所以我们递归调用我们的函数

7.Un-Choose:我们退回,删除所选的方案,以尝试其他选项

具体步骤

  1. 从每一行开始判断,顺序在当前行的列放入Queen,并判断Queen是否合法 (choose)
  2. 重复上述步骤,向下面的行走 (explore)
  3. 若当前行没有放入Queen的合法位置,则回退 (unchoose)
  4. 回退操作直到找到当前Queen的另一个合法位置,否则一直向上面的行回退
  • choose

  技术图片

  • choose

    技术图片

  • unchoose

  技术图片

  • choose

  技术图片

 

  • 重复以上步骤
// 辅助函数,实现回溯法的三个步骤 
void helper(vector<String> res, char[][] board, int rowIndex){
    // 如果到最后一行,返回结果 
    if(rowIndex == board.length){
        res.add(generate(board));
        return;
    }
    // 依次对当前行的每列位置判断是否能放Queen 
    for(int colIndex = 0; colIndex < board.length; colIndex++){
        if(isValid(board, rowIndex, colIndex)){
            // 确定当前行Queen的位置 
            board[rowIndex[colIndex]] = Q;
            // 确定完当前行的Queen之后,转到下一行,确定Queen的故事 
            helper(res, board, rowIndex + 1);
            // 确定完Queen的位置后,对其他位置填 ‘.‘  
            board[rowIndex][colIndex] = .;
        }
    }
}
// 判断位置是否合法 
bool bollean isValid(char[][] board, int rowIndex, int colIndex){
    // 由于从第一行开始向下走,只需要判断当前行的列以及对角线的左上和右上是否有可攻击的Queen 
    // 判断列是否有可攻击的Queen 
    for(int i = 0; i < rowIndex; i++){
        if(board[i][colIndex] == Q){
            return false;
        }
    }
    // 判断对角线上是否有可攻击的Queen 
    // 左上 
    for(int i = rowIndex - 1, i < colIndex - 1; i >= 0 && j >= 0; i--, j--){
        if(board[i][j] == Q){
            return false;
        }
    }
    // 右上 
    for(int i = rowIndex - 1, i < colIndex + 1; i >= 0 && j < board.length 0; i--, j++){
        if(board[i][j] == Q){
            return false;
        }
    }
    return true;
}
// 将board初始化为 ‘.‘ 
void init(char[][] board){
    for(int i = 0; i < board.length; i++){
        for(int j = 0; j < board.length; j++){
            board[i][j]; 
        }        
    }
}
// 生成一个解 
vector<String> generate(char[][] board){
    vector<String> res;
   string s1();
   int totalnums =
sizeof(board) / sizeof(char);
   int rows = sizeof(board[0]) / sizeof(char);
int cols = totalnums / rows;
    for(int i = 0; i < rows; i++){  
    for(int j = 0; j < cols; j++){
      s1 += board[i][j]
    }
   }
   res.push_back(s1);
}
int main(){
   int n = 8; vector
<vector<String>> res; char[][] board = new char[n][n]; init(board); helper(vector<vector<String>> res , char[][] board, rowIndex);
  // 输出 res
return 0; }

以上是关于八皇后(回溯法)的主要内容,如果未能解决你的问题,请参考以下文章

回溯法八皇后问题(递归和非递归)

八皇后回溯计算法研究

每天刷个算法题20160519:回溯法解八皇后

回溯法解决八皇后问题

八皇后(回溯法)

回溯法和八皇后问题