码迷,mamicode.com
首页 > 其他好文 > 详细

【Sudoku Solver】cpp

时间:2015-05-28 23:04:05      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:

题目:

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的效率可能高一些。

【Sudoku Solver】cpp

标签:

原文地址:http://www.cnblogs.com/xbf9xbf/p/4537044.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!