Leetcode0037--Sudoku Solver 数独游戏

【转载请注明】http://www.cnblogs.com/igoslly/p/8719622.html

 

来看一下题目:

       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.

题目意思:

完成数独游戏的计算

在做这题的前两天,楼主正在摸索华为笔试题的时候,已经写了一个非常直白的实现,具体链接如下:

http://www.cnblogs.com/igoslly/p/8708960.html

不过和原题有些区别:① 所有数据均以字符串形式保存  ②  需要填写的位置以 “.” 代替 0

我们稍稍修改下代码,就可以得到实现方法1

bool check(int n,char key,vector<vector<char>> num){
    for(int i=0;i<9;i++){
        int j=n/9;
        if(num[j][i]==key)
        {
            return false;
        }
    } 
    for(int i=0;i<9;i++)
    {
        int j=n%9;
        if(num[i][j]==key){return false;}
    }
    
    int x=n/9/3*3;
    int y=n%9/3*3;
    for(int i=x;i<x+3;i++){
        for(int j=y;j<y+3;j++){
            if(num[i][j]==key){return false;}
        }
    }
    return true;
}
void dfs(int n,vector<vector<char>> &num,bool *sign){
    if(n>80)
    {
        *sign=true;
        return;
    }
    if(num[n/9][n%9]!='.')
    { 
        dfs(n+1,num,sign);
    }else{
        for(char i='1';i<='9';i++)
        {
            if(check(n,i,num)==true){
                num[n/9][n%9]=i;
                dfs(n+1,num,sign);
                if(*sign==true) return;
            }
        }
        num[n/9][n%9]='.';
    }
}
class Solution {
public:
    void solveSudoku(vector<vector<char>>& board) {
        bool sign=false;
        dfs(0,board,&sign);
    }
};

实现方法2:

        优化check函数,将原先逐行、逐列遍历进行判断的方法 → 记录每行、每列、每九宫格是否含有当前数字

        具体实施较原先冗长的代码简短太多)

    // line[i][j],column[i][j],subcube[i][j] 分别代表数独每行、每列、每个子单元是否含有数字j(对应1-9)
    bool line[9][9],column[9][9],subcube[9][9];

        进行dfs前,首先要对原题给出的数字进行记录

// 将所有数组置为false
        memset(line,false,sizeof(line));
        memset(column,false,sizeof(column));
        memset(subcube,false,sizeof(subcube));
        // 根据题意,设定初始数组的值
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                if(board[i][j]=='.')
                    continue;
                
                int num=board[i][j]-'1';
                // 给定题目存在问题,无解,直接返回
                int cube=i/3*3 + j/3;
                if(line[i][num] || column[j][num] || subcube[cube][num])   
                    return ;
                line[i][num] = column[j][num] = subcube[cube][num] = true;
            }
        }

实现方法3:

      在实现方法1中,我们使用 n = 0~80 来记录当前填充空格,根据 n 是否越界判断数独填充是否完成。

      当然我们也可以采用 i & j / row & col 对位置进行记录,更为直观;

      逐行进行填充时,需要对 j > 8 (初始 0)进行换行操作:

// 当j>8时,i++,否则 i 值不变
// 当j>8时,及时取余,重新从0~8计算
(i,j)  -> (i+(j+1)/9,(j+1)%9)

       具体递归代码:

    bool step(vector<vector<char>>&board,int i,int j){
        if(i==9)
            return true;
        if(board[i][j]!='.')
        {
            if(i==8&&j==8){
                return true;
            }
            else{
                return step(board,i+(j+1)/9,(j+1)%9);   // step里值表示i,j换行
            }
        }
         
        int cube=i/3*3 + j/3;
        for(int k=0;k<9;k++){
            if(line[i][k] || column[j][k] || subcube[cube][k])
                continue;
            line[i][k] = column[j][k] = subcube[cube][k] = true;
            board[i][j] = '1'+k;

            if(step(board,i+(j+1)/9,(j+1)%9))    // 若数独已完成,直接返回true
                return true;
            line[i][k] = column[j][k] = subcube[cube][k] = false;
            board[i][j] = '.';
        }
        return false;
    }
posted @ 2018-04-05 02:34  Arya.Mo  阅读(409)  评论(0编辑  收藏  举报