前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Leetcode题目037-解数独

Leetcode题目037-解数独

作者头像
用户6021899
发布2022-11-18 14:12:53
2740
发布2022-11-18 14:12:53
举报

磨了两个晚上的回溯算法,C++不熟,回溯算法也不熟......

老是出不来结果,打印中间结果发现 解 一闪而过,随后被覆盖。

最终定位到原因是 用于回溯的变量不能用于保存问题的解,会被覆盖。得借用另一个全局变量保存解。

代码语言:javascript
复制
#include<vector>
#include<unordered_set>
#include<iostream>
using namespace std;


class Solution
{
public:

    vector<vector<char>> result;

    void solveSudoku(vector<vector<char>>& board)
{
        vector<char> candidates = cal_candidates(board, 0, 3);
        //for (auto ch : candidates)
        //{
        //    cout << ch;
        //}
        //cout << endl;
        vector<vector<int>> to_be_filled = cal_to_be_filled(board);
        int N = to_be_filled.size();
        backtrace(0, board,to_be_filled);
        board = result;
    }


    vector<char> cal_candidates(vector<vector<char>>& board, int row, int col)
    {
        //计算每个位置的候选数字
        vector<char> res;
        if (board[row][col] != '.') return res;
        unordered_set<char> used_chars; //无序集合
        // 计算已经用过的数字,包含空位符号 ‘.'
        for (int i = 0; i < 9; i++) used_chars.insert(board[i][col]);
        for (int i = 0; i < 9; i++) used_chars.insert(board[row][i]);
        int R = row / 3;
        int C = col / 3;
        for(int i = 3 * R; i < 3 * R + 3; i++)
        {
            for (int j = 3 * C; j < 3 * C + 3; j++)
            {
                //cout << board[i][j];
                if (i != row && j != col)
                    used_chars.insert(board[i][j]);
            }
        }


        vector<char> all={'1','2','3','4','5','6','7','8','9'};
        for (char ch : all)
        {
            if (used_chars.find(ch) == used_chars.end())//找不到!
                res.push_back(ch); // 没用过的 做候选
        }


        return res;
    }


    vector<vector<int>> cal_to_be_filled(vector<vector<char>>& board)
    {
        //计算哪些位置空缺,需要填入数字
        vector<vector<int>> res;
        for (int i = 0; i < 9; i++)
        {
            for (int j = 0; j < 9; j++)
            {
                if (board[i][j] == '.') 
                    res.emplace_back(vector<int>{ i, j });
            }
        }
        return res;
    }
    
    
    void backtrace(int start, vector<vector<char>>& board, vector<vector<int>>& to_be_filled) //
{
        
        if (start == to_be_filled.size()) //退出条件。全部填完,的下一个不存在的位置
        {
            result = board; //需要另一个全局变量保存解。因为它会一闪而过......
            return;
        }


        //if (start == to_be_filled.size()) return;
        int row = to_be_filled[start][0];
        int col = to_be_filled[start][1];
            
        vector<vector<char>> temp = board; //备份,以待回溯
        vector<char> candidates = cal_candidates(board, row, col);
        for (char candidate : candidates)
        {
            //cout << row << "," << col << " =? " << candidate << endl;
            board[row][col] = candidate;
            backtrace(start + 1, board, to_be_filled); //进入下一层调用
            board = temp;//回溯
            //注意,在最后一层找到解后,会返回上一层,board会改变,(如果用board保存解)会丢失解的保存
            //board = temp 会让board 复原状态,也会丢失解的保存。所以需要另一个变量全局变量保存解
        }
    }


    void print_board(vector<vector<char>>& board)
{
        for (auto v_row : board)
        {
            for (auto c : v_row)
            {
                cout << c << ' ';
            }
            cout << endl;
        }
    }
}; 



int main(void)
{
    Solution sol;
    //vector<vector<char>> board(9,vector<char>(9));


    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'} };
    vector<vector<int>>tobe = sol.cal_to_be_filled(board);
    cout << "有"<<tobe.size() <<"个位置需要填入" <<endl;
    sol.solveSudoku(board);
    cout << endl;
    cout << "最终结果" << endl;
    sol.print_board(sol.result);
    return 0;
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-11-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python可视化编程机器学习OpenCV 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档