回溯法遵循深度优先吗_回溯算法(DFS:深度优先)

1. 八皇后问题

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

思路:使用一个数组gEightQueen存储第i行的皇后摆在第gEightQueen[i]列的位置上

步骤一:对于第0行,一共有八个位置可以选择,逐一选择

步骤二:对于以后的每一行,一共有八个位置可以选择,确定位置后需要判断该位置放置元素是否与前面的行冲突,如果冲突,继续在剩余的位置中选择测试。如果不冲突,则继续向下递归,递归结束后应当将改行的元素置0。

步骤三:当递归到第7行,选择位置不冲突则找到了一种情况,将总的情况统计数加1。

#include

using namespacestd;static int gEightQueen[8] = { 0 }, gCount = 0;void print()//输出每一种情况下棋盘中皇后的摆放情况

{for (int i = 0; i < 8; i++)

{intinner;for (inner = 0; inner < gEightQueen[i]; inner++)

cout<< "0";

cout<

cout<< "0";

cout<

}

cout<< "==========================\n";

}int check_pos_valid(int loop, int value)//检查是否存在有多个皇后在同一行/列/对角线的情况

{intindex;intdata;for (index = 0; index < loop; index++)

{

data=gEightQueen[index];if (value ==data)return 0;if ((index + data) == (loop +value))return 0;if ((index - data) == (loop -value))return 0;

}return 1;

}void eight_queen(intindex)

{intloop;for (loop = 0; loop < 8; loop++)

{if(check_pos_valid(index, loop))

{

gEightQueen[index]=loop;if (7 ==index)

{

gCount++, print();

gEightQueen[index]= 0;return;

}

eight_queen(index+ 1);

gEightQueen[index]= 0;

}

}

}int main(int argc, char*argv[])

{

eight_queen(0);

cout<< "total=" << gCount <

}

2. 数独问题

解法:只需要求出一个解,solve()返回布尔类型对于判断是否完成解十分有用

步骤一:依此遍历数独中所有的元素,如果不存在'.',说明已经获得了解,如果存在'.',说明需要继续向下求解。

步骤二:存在'.',依此遍历字符1-9,判断是否满足行,列条件,如果满足,将该值赋给'.'所在位置的元素,继续向下求解,如果有解,返回true,解已经求得,如果没有解,将'.'所修改的值继续改到'.',否则在判断有效性的函数上会出现问题。

#include "pch.h"#include#include

using namespacestd;bool isValid(vector>& board, int row, int col, charvalue) {//测试行,列,3 * 3 矩阵有效

for (int i = 0; i < board.size(); i++) {if (board[row][i] ==value) {return false;

}if (board[i][col] ==value) {return false;

}if (board[i / 3 + 3 * (row / 3)][i % 3 + 3 * (col / 3)] ==value) {return false;

}

}return true;

}bool solve(vector>&board) {for (int i = 0; i < board.size(); i++) {for (int j = 0; j < board[0].size(); j++) {if (board[i][j] == '.') {for (char k = '1'; k <= '9'; k++) {if(isValid(board, i, j, k)) {

board[i][j]=k;if(solve(board)) {return true;

}

board[i][j]= '.'; //更换一个k值继续计算

}

}return false;

}

}

}return true;

}void solveSudoku(vector>&board) {if (board.empty() || board.size() == 0) {return;

}

solve(board);

}intmain() {

vector> board = { {'5', '3', '.', '.', '7', '.', '.', '.', '.'},

{'6', '.', '.', '1', '9', '5', '.', '.', '.'},

{'.', '9', '8', '.', '.', '.', '.', '6', '.'},

{'8', '.', '.', '.', '6', '.', '.', '.', '3'},

{'4', '.', '.', '8', '.', '3', '.', '.', '1'},

{'7', '.', '.', '.', '2', '.', '.', '.', '6'},

{'.', '6', '.', '.', '.', '.', '2', '8', '.'},

{'.', '.', '.', '4', '1', '9', '.', '.', '5'},

{'.', '.', '.', '.', '8', '.', '.', '7', '9'} };

solveSudoku(board);for (int i = 0; i < board.size(); i++) {for (int j = 0; j < board[0].size(); j++) {

cout<< board[i][j] << ' ';

}

cout<

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值