• 【Sudoku Solver】cpp


    题目:

    Write a program to solve a Sudoku puzzle by filling the empty cells.

    Empty cells are indicated by the character '.'.

    You may assume that there will be only one unique solution.

    A sudoku puzzle...

    ...and its solution numbers marked in red.

    代码:

    class Solution {
    public:
            void solveSudoku(vector<vector<char> >& board)
            {
                vector<pair<int, int> > emptyCells;
                vector<set<char> > rowSet, colSet, matrixSet;
                set<char> row, col, matrix;
                for ( size_t i = 0 ; i < 9; ++i )
                {
                    row.clear(); col.clear(); matrix.clear();
                    for ( size_t j = 0 ; j < 9; ++j )
                    {
                        if (board[i][j]!='.'){
                            row.insert(board[i][j]);
                        }
                        else{
                            emptyCells.push_back(make_pair(i, j));
                        }
                        if (board[j][i]!='.') col.insert(board[j][i]);
                        int r = j/3+(i/3)*3, c = j%3+(i%3)*3;
                        if (board[r][c]!='.') matrix.insert(board[r][c]);
                    }
                    rowSet.push_back(row); colSet.push_back(col); matrixSet.push_back(matrix);
                }
                Solution::dfs(board, emptyCells, rowSet, colSet, matrixSet);
            }
            static bool dfs(
                vector<vector<char> >& board,
                vector<pair<int, int> >& emptyCell,  
                vector<set<char> >& rowSet,
                vector<set<char> >& colSet,
                vector<set<char> >& matrixSet)
            {
                if ( emptyCell.empty() ) return true;
                int i = emptyCell.back().first;
                int j = emptyCell.back().second;
                for ( char v = '1'; v<='9' && !emptyCell.empty(); ++v )
                {
                    if (rowSet[i].find(v)==rowSet[i].end() && 
                        colSet[j].find(v)==colSet[j].end() &&  
                        matrixSet[(i/3)*3+j/3].find(v)==matrixSet[(i/3)*3+j/3].end() )
                    {
                        board[i][j]=v;
                        rowSet[i].insert(v);
                        colSet[j].insert(v);
                        matrixSet[(i/3)*3+j/3].insert(v);
                        emptyCell.pop_back();
                        if ( Solution::dfs(board, emptyCell, rowSet, colSet, matrixSet) )
                        {
                            return true;
                        }
                        else
                        {
                            emptyCell.push_back(make_pair(i, j));
                            board[i][j] = '.';
                            rowSet[i].erase(v);
                            colSet[j].erase(v);
                            matrixSet[(i/3)*3+j/3].erase(v);
                        }
                    }
                }
                return false;
            }
    };

    tips:

    采用深搜模板。

    主要思路走一遍board,得到三个set,一个vector

    1. 三个set分别为每行、列、子模块已有的数字

    2. 一个vector中存放着'.'的位置

    每次处理一个'.',遍历1到9:

    1. 如果满足数独的条件,就往下走一层

    2. 如果1到9都不满足,则退回到上一层,重新选择上一个位置的元素

    这里有一个思维陷阱:

                        emptyCell.pop_back();
                        if ( Solution::dfs(board, emptyCell, rowSet, colSet, matrixSet) )
                        {
                            return true;
                        }
                        else
                        {
                            emptyCell.push_back(make_pair(i, j));
                            board[i][j] = '.';
                            rowSet[i].erase(v);
                            colSet[j].erase(v);
                            matrixSet[(i/3)*3+j/3].erase(v);
                        }

    注意:pop和push操作应该是对应的,之前一直以为可以不用push的操作,原因是忽略了一种情况:如果一个位置从1到9都不满足,那么必然要回溯到上一层;即,某一个位置的元素是可能遍历不止一次1到9的。

    =================================

    这里set的效率可能有些低,换一个hashmap的效率可能高一些。

    class Solution {
    public:
            void solveSudoku(vector<vector<char> >& board)
            {
                vector<pair<int, int> > emptyCells;
                vector<map<char,bool> > rowSet, colSet, matrixSet;
                map<char,bool> row, col, matrix;
                for ( size_t i = 0 ; i < 9; ++i )
                {
                    for ( char v = '1' ; v <= '9'; ++v ) { row[v] = col[v] = matrix[v] = false; }
                    for ( size_t j = 0 ; j < 9; ++j )
                    {
                        if (board[i][j]!='.'){
                            row[board[i][j]] = true;
                        }
                        else{
                            emptyCells.push_back(make_pair(i, j));
                        }
                        if (board[j][i]!='.') col[board[j][i]]=true;
                        int r = j/3+(i/3)*3, c = j%3+(i%3)*3;
                        if (board[r][c]!='.') matrix[board[r][c]]=true;
                    }
                    rowSet.push_back(row); colSet.push_back(col); matrixSet.push_back(matrix);
                }
                Solution::dfs(board, emptyCells, rowSet, colSet, matrixSet);
            }
            static bool dfs(
                vector<vector<char> >& board,
                vector<pair<int, int> >& emptyCell,  
                vector<map<char,bool> >& rowSet,
                vector<map<char,bool> >& colSet,
                vector<map<char,bool> >& matrixSet)
            {
                if ( emptyCell.empty() ) return true;
                int i = emptyCell.back().first, j = emptyCell.back().second;
                for ( char v = '1'; v<='9'; ++v )
                {
                    if (!rowSet[i][v] && !colSet[j][v] &&  !matrixSet[(i/3)*3+j/3][v] )
                    {
                        board[i][j] = v;
                        rowSet[i][v] = colSet[j][v] = matrixSet[(i/3)*3+j/3][v] = true;
                        emptyCell.pop_back();
                        if ( Solution::dfs(board, emptyCell, rowSet, colSet, matrixSet) ){
                            return true;
                        }
                        else{
                            emptyCell.push_back(make_pair(i, j));
                            rowSet[i][v] = colSet[j][v] = matrixSet[(i/3)*3+j/3][v] = false;
                        }
                    }
                }
                return false;
            }
    };

    tips:都换成了hashmap,效率有所提升。

    ============================================

    第二次过这道题,还是sub board那块内容调了几次,AC了。

    class Solution {
    public:
            void solveSudoku(vector<vector<char> >& board)
            {
                // restore all blank positions
                vector<pair<int, int> > blanks;
                for ( int i=0; i<board.size(); ++i )
                {
                    for ( int j=0; j<board[i].size(); ++j )
                    {
                        if ( board[i][j]=='.' ) blanks.push_back(make_pair(i, j));
                    }
                }
                Solution::dfs(board, blanks);
            }
            static bool dfs(
                vector<vector<char> >& board, 
                vector<pair<int,int> >& blanks )
            {
                if ( blanks.empty() ) return true;
                const int r = blanks.back().first;
                const int c = blanks.back().second;
                for ( char v='1'; v<='9'; ++v )
                {
                    bool valid = true;
                    // check row & column & subBoard
                    for ( int i=0; i<9; ++i )
                    {
                        if ( board[r][i]==v || board[i][c]==v || board[i/3+(r/3)*3][i%3+(c/3)*3]==v )
                        {
                            valid = false;
                            break;
                        }
                    }
                    if ( valid )
                    {
                        board[r][c] = v;
                        blanks.pop_back();
                        if ( Solution::dfs(board, blanks) ) return true;
                        blanks.push_back(make_pair(r, c));
                        board[r][c] = '.';
                    }
                }
                return false;
            }
    };
  • 相关阅读:
    下定决心
    SPFA
    Linux下一些常用的命令
    如何设计符合RESTful风格的API
    django中的第三方:富文本编辑器和itsdangerous加密
    redis主从
    redis集群
    django中关联(一对多)查询的两种方式,理一理
    关于Django中的迁移文件
    日常工作中Git的正确使用姿势
  • 原文地址:https://www.cnblogs.com/xbf9xbf/p/4537044.html
Copyright © 2020-2023  润新知