回溯算法就是个多叉树的遍历问题, 关键就是在前序遍历和后序遍历的位置做⼀些操作, 算法框架如下:
void backTrack(...){
if(满足结束条件){
将路径加入到结果集
return ;
}
for(选择 in 选择列表){
判断选择是否合法,如果不合法则进入一下此循环(continue)
并做选择
进入下一层决策树(backTrack(...))
撤销选择(也就是回溯的意思)
}
}
写backTrack
函数时,需要维护走过的[路径]和当前可以做的[选择列表],当触发[结束条件]时,将[路径]加入到结果集。
举个例子八皇后问题,数组使用result[8]太妙了,切忌不要使用二维数组result,这样反而会增大难度,因为使用result[8]的话,每行路径在找到正确位置都是更新的最新值;如果使用二维数组的话,还要考虑当皇后回溯的时候,怎么去掉放置的位置。
- 这个题目在判断皇后位置是否合适的时候,只需要判断当前行上方的位置是否有皇后,不需要判断下面的
- 一定要注意,数组result最后的值可能不是八皇后,可能是某个中间值,所以,不要在最后来打印八皇后,应该在8个皇后都放置好了就可以打印了。
C++版代码如下
#include <iostream>
#include <math.h>
#include <cstring>
using namespace std;
#define MAXSIZE 256
// 八皇后问题
bool isOk(int result[], int row, int col){
// 只判断row行之前的位置,后面的不管
// 1、判断竖方向
for(int i = 0; i <= row - 1; i++){
if(result[i] == col)
return false;
}
// 2、判断主对角线左方
for(int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--){
if(result[i] == j)
return false;
}
// 3、 判断副对角线右方
for(int i = row - 1, j = col + 1; i >= 0 && j < 8; i--, j++){
if(result[i] == j)
return false;
}
return true;
}
void eightQueen(int result[], int row){
// 如果走到了最后一行,则代表找到了全部位置
if(row == 8){
for (int row = 0; row < 8; ++row) {
for (int column = 0; column < 8; ++column) {
if (result[row] == column)
cout<<"Q ";
else
cout<<"* ";
}
cout<<endl;
}
cout<<endl;
return ;
}
// 此行所有列
for(int col = 0; col < 8; col++){
// 第row行col列放置皇后
if(isOk(result, row, col)){
// 这一列找到位置,走到下一行去继续找
result[row] = col;
eightQueen(result, row + 1);
}
}
}
int main(int argc, char* argv[]){
int result[8];
memset(result, 127, sizeof(result));
eightQueen(result, 0);
return 0;
}
按照开头的算法框架的版本代码:
vector<vector<string>> res;
vector<vector<string>> solveNQueens(int n){
// 初始化棋盘
vector<string> board(n, string(n, '.'));
backTrack(board, 0);
return ans;
}
void backTrack(vector<string> &board, int row){
// 触发结束条件
if(row == board.size()){
// 将路径加入到结果集中
res.push_back(board);
return ;
}
int cols = borad[row].size();
for(int col = 0; col < cols; col++){
// 判断选择是否合法
if(isOk(row, col)){
// 做选择
board[row][col] = 'Q';
// 进入下一层决策树
backTrack(board, row + 1);
// 撤销选择
board[row][col] = '.';
}
}
}