【C语言刷LeetCode】37. 解数独(H)

编写一个程序,通过已填充的空格来解决数独问题。

一个数独的解法需遵循如下规则

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

空白格用 '.' 表示。

数独和N-皇后问题,算法的经典题,这次总算把数独的解决了。

此问题有个关键点,也是参考别人的实现,就是如何计算3*3模块的索引,k = (i / 3) * 3 + j / 3。

第一步是根据已有数字完成标记,行列块都需要。

然后就是一个方格一个方格的回溯递归,当行、列、块均不冲突时填入数字,继续下一个方块回溯递归。

当有方块冲突了,所有的数字尝试完了后,只能一个个再回退了,吃了我的都给我吐出来。

最终得到题目的结果。

int row[9][9];
int col[9][9];
int blk[9][9];

int dfs(char **board) {
    int i,j,k,l;
    
    for (i = 0; i < 9; i++) {
        for(j = 0; j < 9; j++) {
            if(board[i][j] == '.') {
                k = (i / 3) * 3 + j / 3;
                for (l = 0; l < 9; l++) {
                    if ((row[i][l] == 0) && (col[j][l] == 0) && (blk[k][l] == 0)) {
                        board[i][j] = l + '0' + 1;
                        row[i][l] = 1;
                        col[j][l] = 1;
                        blk[k][l] = 1;
                        if (dfs(board)) {
                            return 1;
                        }

                        row[i][l] = 0;
                        col[j][l] = 0;
                        blk[k][l] = 0;
                        board[i][j] = '.';
                    }
                } // 这个位置尝试了9个数,还是不行,那便是真不行了,return 0吧
                return 0;
            }
        }
    } 
    return 1; // for循环都结束了,一个空缺都没有,那就是填满了
}

void solveSudoku(char** board, int boardSize, int* boardColSize){
    int i, j, k, num;

    memset(row, 0, sizeof(int) * 81);
    memset(col, 0, sizeof(int) * 81);
    memset(blk, 0, sizeof(int) * 81);

    for (i = 0; i < 9; i++) {
        for (j = 0; j < 9; j++) {
            if (board[i][j] == '.') continue;
            num = board[i][j] - '0' - 1;
            row[i][num] = 1;
            col[j][num] = 1;
            k = (i / 3) * 3 + j / 3; // 这一句很关键
            blk[k][num] = 1;
        }
    }

    dfs(board);
}

 

你可能感兴趣的:(LeetCode)