数独(dfs解)

Posted zhixiangshu

tags:

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

蒜头君今天突然开始还念童年了,想回忆回忆童年。他记得自己小时候,有一个很火的游戏叫做数独。便开始来了一局紧张而又刺激的高阶数独。蒜头君做完发现没有正解,不知道对不对? 不知道聪明的你能否给出一个标准答案?

标准数独是由一个给与了提示数字的 9×9 网格组成,我们只需将其空格填上数字,使得每一行,每一列以及每一个 3×3 宫都没有重复的数字出现。

技术图片

输入:

* 2 6 * * * * * *
* * * 5 * 2 * * 4
* * * 1 * * * * 7
* 3 * * 2 * 1 8 *
* * * 3 * 9 * * *
* 5 4 * 1 * * 7 *
5 * * * * 1 * * *
6 * * 9 * 7 * * *
* * * * * * 7 5 *

输出:

1 2 6 7 3 4 5 9 8
3 7 8 5 9 2 6 1 4
4 9 5 1 6 8 2 3 7
7 3 9 4 2 5 1 8 6
8 6 1 3 7 9 4 2 5
2 5 4 8 1 6 3 7 9
5 4 7 2 8 1 9 6 3
6 1 3 9 5 7 8 4 2
9 8 2 6 4 3 7 5 1

提醒:两个数字之间要有一个空格,其他地方不要输出多余的符号

示例代码:

/**
    关于数组xv,yv,vv起的标记作用
    其思想其实也很简单,就是做到数独上面的格子能够和xv,yv,vv上的格子有个对应关系 
    感觉深搜基本上都会用到数组标记的技巧(用来回溯) 
*/ 
#include<cstdio>
char s[10][10]; //存储"棋盘"上的数据 
bool xv[10][10], yv[10][10], vv[10][10];    //用来标记行、列、3x3格子填过数的位置
bool f; 
void dfs(int x, int y) {
    
    if(f) {
        return;
    }
    
    if( x == 9 ) {      //x为9 说明所有的行都填数完毕 
        f = true;
        //所有数字都已经填完,输出填完之后的数独"棋盘" 
        for (int i = 0; i < 9; i ++) {
            for (int j = 0; j < 9; j ++) {
                
                if(j == 8) {
                    printf("%c
",s[i][j]);
                } else {
                    printf("%c ",s[i][j]);
                }
                    
            }
        }
        return;
    }
    
    if( y == 9 ) {      //y为9说明填好一行 
        dfs(x + 1, 0);  //换一行继续填 
        return;
    }
    
    if(s[x][y] != '*') {
        dfs(x, y + 1);
        return;
    }
    
    for(int i = 1; i <= 9; i ++) {
    //printf("%d %d %d
",x, y, i);
        //在符合条件的位置上填数
        if(!xv[x][i] && !yv[y][i] && !vv[x / 3 * 3 + y / 3][i]) {
            xv[x][i] = yv[y][i] = vv[x / 3 * 3 + y / 3][i] = true;    //已经填过的数在对应、列、3x3方格上做好标记
            s[x][y] = i + '0';    //填入数字
            dfs(x, y + 1);
            xv[x][i] = yv[y][i] = vv[x / 3 * 3 + y / 3][i] = false;    //取消填过的数(深搜到某一步发现当前解不符合条件时需要回溯上一个dfs(int x,int y),此时需要取消历史填数以便进行其他试探)
            s[x][y] = '*';
        }
    }
    
}
int main() {
    //输入一个原始的数独数据 
    for(int i = 0; i < 9; i ++ ) {
        for (int j = 0; j < 9; j ++) {
            
            scanf(" %c",&s[i][j]);  //" %c"留了一个空格是为了吃掉输入中的空格
             
            //将已经填好数字的位置 通过 xv yv vv数组做个标记 
            if(s[i][j] != '*') {    
                xv[i][s[i][j] - '0'] = true;
                yv[j][s[i][j] - '0'] = true;
                vv[i / 3 * 3 + j / 3][s[i][j] - '0'] = true;
            }
        }
    }
    dfs(0, 0);
    return 0;
}

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

[dfs] aw166. 数独(dfs剪枝与优化+状态压缩+代码技巧+好题)

数独 dfs

数独 (dfs)

确定数独是不是有唯一解

洛谷 P1784 数独[DFS/回溯]

NYOJ 722 数独(DFS)