【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;
        }
};

 

posted on 2015-05-28 21:46  承续缘  阅读(167)  评论(0编辑  收藏  举报

导航