回溯算法(DFS:深度优先)

1. 八皇后问题

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

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

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

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

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

#include<iostream>
using namespace std;
static int gEightQueen[8] = { 0 }, gCount = 0;
void print()//输出每一种情况下棋盘中皇后的摆放情况
{
    for (int i = 0; i < 8; i++)
    {   
        int inner;
        for (inner = 0; inner < gEightQueen[i]; inner++)
            cout << "0";
            cout <<"#";
        for (inner = gEightQueen[i] + 1; inner < 8; inner++)
            cout << "0";
        cout << endl;
    }
    cout << "==========================
";
}
int check_pos_valid(int loop, int value)//检查是否存在有多个皇后在同一行/列/对角线的情况
{
    int index;
    int data;
    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(int index)
{
    int loop;
    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 << endl;
    return 0;
}

 2. 数独问题

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

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

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

#include "pch.h"
#include <iostream>
#include <vector>

using namespace std;

bool isValid(vector<vector<char>>& board, int row, int col, char value) {
    // 测试行,列,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<vector<char>>& 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<vector<char>>& board) {
    if (board.empty() || board.size() == 0) {
        return;
    }
    solve(board);
}

int main() {
    vector<vector<char>> 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 << endl;
    }
}
原文地址:https://www.cnblogs.com/feng-ying/p/11165932.html