数独(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解)的主要内容,如果未能解决你的问题,请参考以下文章