Sudoku

Posted rign

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Sudoku相关的知识,希望对你有一定的参考价值。





题目来源:POJ 3074 Sudoku
http://poj.org/problem?id=3074

In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns.
The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”.
技术分享图片

这道题目是关于搜索的一道题目,首先我们来分析一下题意
(9cdot9)的方格中,可以填入1-9,但是每行每列每个9宫格不准有重复的数字
于是我们可以尝试每个可以填入格子的位置去深度搜索,但是这个样子就会产生无效的搜索,比如两次不同搜索在填入了相同的数字,只是因为搜索的顺序不同,所以我们要去确定搜索的顺序,防止产生重复的搜索,其次就是,我们不一定需要把1-9每个数字都尝试一遍,因为题目中所给的已知,可以确定未知的位置所能搜索的数字,再者就是关于搜索的状态优化,可以利用二进制可以来优化状态

搜索主体

bool dfs(int now) {
    if (now == 0) return 1;
    int temp = 10, x, y;
    for (int i = 0; i < 9; i++)//确定搜索顺序,找寻可以填数字量最少的位置
        for (int j = 0; j < 9; j++) {
            if (str[i][j] != '.') continue;
            int val = row[i] & col[j] & grid[g(i, j)];
            if (!val) return 0;
            if (cnt[val] < temp) {
                temp = cnt[val];
                x = i, y = j;
            }
        }
    int val = row[x] & col[y] & grid[g(x, y)];//确定该位置可以填的数字
    for (; val; val -= val&-val) {
        int z = num[val&-val];//num是一个二进制和该数字的映射
        str[x][y] = '1' + z;
        flip(x, y, z);
        if (dfs(now - 1)) return 1;//遍历,利用return提前终止
        flip(x, y, z);
        str[x][y] = '.';
    }
    return 0;
}

填入数字时关于某位置的行列格子的数字二进制反转操作

inline int g(int x, int y) {
    return ((x / 3) * 3) + (y / 3);//确定格子
}

inline void flip(int x, int y, int z) {
        //反转
    row[x] ^= 1 << z;
    col[y] ^= 1 << z;
    grid[g(x, y)] ^= 1 << z;
}

预处理

    for (int i = 0; i < 1 << 9; i++)
        for (int j = i; j; j -= j&-j) cnt[i]++;
    for (int i = 0; i < 9; i++)
        num[1 << i] = i;
        for (int i = 0; i < 9; i++) row[i] = col[i] = grid[i] = (1 << 9) - 1;
        for (int i = 0; i < 9; i++)
            for (int j = 0; j < 9; j++)
                if (str[i][j] != '.') flip(i, j, str[i][j] - '1');
                else tot++;
        dfs(tot);

以上是关于Sudoku的主要内容,如果未能解决你的问题,请参考以下文章

Sudoku Solver问题

洛谷OJ 1074 靶型sudoku dfs(搜索顺序优化)

LeetCode 37 Sudoku Solver(求解数独)

Sudoku(简单DFS)

Valid Sudoku

poj2676 Sudoku(搜索)