搜索进阶——数独问题

1.问题描述:

搜索进阶——数独问题_第1张图片
搜索进阶——数独问题_第2张图片
搜索进阶——数独问题_第3张图片

2.问题分析:

这道题目是比较经典的搜索问题,当你学会怎么解八皇后问题的时候,就慢慢的进入了搜索之道,这一道题目比较难的点就是33的格子内填充的数不能重复。行和列不重复很简单,怎么判定重复与否,我们将数独棋盘分为9个33的棋盘并且将其编号:
搜索进阶——数独问题_第4张图片
可以发现规律每一个编号的33的格子为当前的x,y
x / 3 * 3 + y / 3
我们可以在主函数里通过设置判断行,列,3
3格子是否使用,visx[9][9]代表的是该行所用的数,比如visx[0][1]代表的是第0行已经存在数字1了,第0行则不能填充数字1了.visy[9][9]代表的是该列所用的数,比如visy[0][1]代表的是第0列已经存在数字1了,不能够放数字一了,vis3[9][9]代表的是33的格子中存放的数,比如vis3[0][1]代表在0编号中的33的格子已经放了1了则在其余8个格子不能够放1了。

for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            if (map[i][j] != '*') {
                visx[i][map[i][j] - '0'] = true; //因为是字符数组,所以转换为整数需要-'0'
                visy[j][map[i][j] - '0'] = true;
                vis3[i / 3 * 3 + j / 3][map[i][j] - '0'] = true;
            }
        }
    }

然后我们写dfs函数,从行开始搜,当行为9时,说明找到一组正解,我们通过一个bool变量记录,return掉,当列为9时我们搜索下一行也就是dfs(x + 1,0).这里剪枝了一下,当map[x][y] != '*'的时候说明有数了,就不用继续填充了,需要注意的是每次填充后,我们之后需要取消标记,找寻其他的解。

3.源码:

#include 
#include 
using namespace std;

char map[9][9];  //数独棋盘
bool visx[9][9],visy[9][9],vis3[9][9];//visx表示为行的某个数是否使用,visy表示列的某个数是否使用,vis3表示3*3的小格子
bool f;

void dfs(int x,int y) {
    if (f) {
        return;
    }
    if (x == 9) {
        f = true;
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (j != 8) {
                    printf("%c ",map[i][j]);
                } else {
                    printf("%c\n",map[i][j]);
                }
            }
        }
    }
    if (y == 9) {
        dfs(x + 1,0);
        return;
    }
    if (map[x][y] != '*') {
        dfs(x,y + 1);
        return;
    }
    for (int i = 1; i <= 9; i++) {
        if (!visx[x][i] && !visy[y][i] && !vis3[x / 3 * 3 + y / 3][i]) {
            map[x][y] = i + '0';
            visx[x][i] = true;
            visy[y][i] = true;
            vis3[x / 3 * 3 + y / 3][i] = true;
            dfs(x, y + 1);
            visx[x][i] = false;
            visy[y][i] = false;
            vis3[x / 3 * 3 + y / 3][i] = false;
            map[x][y] = '*';
        }
    }
}

int main() {
    for (int i = 0; i < 9; i++) {
       for (int j = 0; j < 9; j++) {
           scanf(" %c",&map[i][j]);
       }
    }
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            if (map[i][j] != '*') {
                visx[i][map[i][j] - '0'] = true;
                visy[j][map[i][j] - '0'] = true;
                vis3[i / 3 * 3 + j / 3][map[i][j] - '0'] = true;
            }
        }
    }
    dfs(0,0);
    return 0;
}

欢迎关注Blog:
www.lyxueit.com
大家一起学习交流。

你可能感兴趣的:(Oj,C++,计蒜客,DFS,搜索)