• 回溯算法(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;
        }
    }
  • 相关阅读:
    终端提示“ timed out waiting for input: auto-logout”
    shell-日志统计
    spring-file-upload-exceeds its maximum permitted size of 1048576 bytes
    全面质量管理 TQM、六西格玛、CMMI、ISO9000 关系
    GitLab: You are not allowed to force push code to a protected branch on this project.
    go 多版本管理
    glide install error
    js tab栏切换
    ES6 class命令浅识
    ES6 const命令
  • 原文地址:https://www.cnblogs.com/feng-ying/p/11165932.html
Copyright © 2020-2023  润新知