【刷题笔记30 回溯算法 part06】

回溯算法

● 332.重新安排行程
● 51. N皇后
● 37. 解数独
● 总结

重新安排行程

332.重新安排行程

法1:回溯

  unordered_map<string,map<string,int>> targets;
    //记录机场数:int ticketNum,记录航班:vector<string>ans
    bool backTracking(int ticketNum,vector<string>& ans){
        if (ticketNum + 1 == ans.size()) {
            return true;
        }
        for (auto &p: targets[ans[ans.size() - 1]]){
            if (p.second > 0){
                ans.push_back(p.first);
                p.second--;
                if (backTracking(ticketNum,ans)) return true;
                p.second++;
                ans.pop_back();
            }
        }
        return false;

    }
    vector<string> findItinerary(vector<vector<string>>& tickets) {
        vector<string> ans;
        //init targets
        targets.clear();
        for (const auto &vec: tickets){
            targets[vec[0]][vec[1]]++;
        }
        ans.push_back("JFK");
        backTracking(tickets.size(),ans);
        return ans;
    }

N皇后

51. N皇后
法1: 回溯

 vector<vector<string>>ans;
    void backTracking(int n,int row,vector<string>& chessBoard){
        //终止
        if (row == n){
            ans.push_back(chessBoard);
            return;
        }
        //单层搜索
        for (int col = 0; col < n; ++col) {
            if (isVaild(row,col,chessBoard,n)){
                //满足N皇后条件
                chessBoard[row][col] = 'Q';
                backTracking(n,row + 1,chessBoard);
                chessBoard[row][col] = '.';
            }
        }
    }

    bool isVaild(int row,int col,vector<string>& chessBoard, int n){
        //检查列
        for (int i = 0; i < row; ++i) {
            if (chessBoard[i][col] == 'Q'){
                return false;
            }
        }
        //检查45度
        for (int i = row - 1,j = col - 1; i >= 0 && j >=0; i--,j--) {
            if (chessBoard[i][j] == 'Q'){
                return false;
            }
        }
        //检查135度
        for (int i = row - 1,j = col + 1; i >= 0 && j  < n; i--,j++) {
            if (chessBoard[i][j] == 'Q'){
                return false;
            }
        }
        return true;
    }
    vector<vector<string>> solveNQueens(int n) {
        ans.clear();
        //vector<string> chessBoard;
        std::vector<std::string> chessBoard(n, std::string(n, '.'));
        backTracking(n,0,chessBoard);
        return ans;
    }

解数独

37. 解数独

法1:回溯

//回溯
    bool backTracking(vector<vector<char>>& board){
        //遍历行
        for (int row = 0; row < board.size(); ++row) {
            //遍历列
            for (int col = 0; col < board[0].size(); ++col) {
//                if (board[row][col] != '.')continue;
                if (board[row][col] == '.') {
                    for (char i = '1'; i <= '9'; ++i) {
                        //该位置放1-9数字的可能性
                        if (isVaild(board,i, row, col)) {
                            //递归
                            board[row][col] = i;
                            if (backTracking(board))return true;
                            //回溯
                            board[row][col] = '.';
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }
    bool isVaild(vector<vector<char>>& board, char c,int row, int col){//丢失传过来的字符
        //何时返回true??最后所有雷均已躲避
        //行有效
        for (int i = 0; i < 9; ++i) {
            if (board[row][i] == c)return false;
        }
        //列有效
        for (int j = 0; j < 9; ++j) {
            if (board[j][col] == c) return false;
        }
        //九宫格有效 此处需谨慎
        int startRow = (row / 3) *3;
        int startCol = (col / 3) *3;
        for (int i = startRow; i < startRow + 3; ++i) {
            for (int j = startCol; j < startCol + 3; ++j) {
                if (board[i][j] == c) return false;
            }
        }
        return true;
    }
    void solveSudoku(vector<vector<char>>& board) {
        backTracking(board);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值