数独游戏题解.(DFS)
9、数独游戏.
【问题描述】
在9×9的矩阵中,使行、列的单位元素都为1到9的数字,不得有重复,并且把矩阵从左到右,从上到下平分成9个块,每块3×3,每块的元素也是1到9的数字,不得有重复。每个矩阵的答案是唯一的。
可能的输入如下图所示:
3 | 9 | 2 | 1 | 5 | 8 | |||
5 | 7 | |||||||
8 | 2 | 6 | ||||||
2 | ||||||||
2 | 1 | 7 | 6 | |||||
7 | ||||||||
5 | 4 | 8 | ||||||
2 | 3 | |||||||
5 | 6 | 1 | 8 | 3 | 9 |
(空缺位数字用0表示).
【题目分析】
该题目使用dfs可解,
首先建立数组来标记该地方是否有数据
int suduku[9][10]; //存放数独数据
int H[9][10]; //标记是否在第 i行出现过
int L[9][10]; //标记是否在第 i 列出现过
int S[9][10]; //标记是否在第 i个小方块出现过
然后利用for循环输入数独数据并进行标记.
for(i=0; i<9; i++) {
char temp[10];
scanf("%s",temp);
for(j=0; j<9; j++) {
suduku[i][j]=temp[j]-'0'; //转化为数字
if(suduku[i][j]) {
int k=i/3*3+j/3; //求出此时在第几个小方块里
H[i][suduku[i][j]]=1;// 将suduku[i][j]出现在i行进行标记
L[j][suduku[i][j]]=1;// 将suduku[i][j]出现在j列进行标记
S[k][suduku[i][j]]=1;// 将suduku[i][j]出现在第k个方块中标记
}
}
}
然后递归深搜.
if(suduku[x][y]) {
if(y==8) Dfs(x+1,0);
else Dfs(x,y+1);
} else {
int num;
for(num=1; num<=9; num++) { //从 1 到 9 枚举数字
int k=x/3*3+y/3;//第k个小正方形.
if(!L[y][num]&&!H[x][num]&&!S[k][num]) { //如果该行该列该小正方形未曾填入数字,三项验证.
suduku[x][y]=num;//将num填入数独数组.
L[y][num]=1;//将已填入的信息更新
H[x][num]=1;
S[k][num]=1;
if(y==8) Dfs(x+1,0);
else Dfs(x,y+1);
suduku[x][y]=0;
L[y][num]=0;
H[x][num]=0;
S[k][num]=0;
}
}
}
当将数独数组补充完整后进行输出.
if(x==9) {//当处于第九行时
isdone=1;
int i,j;
for(i=0; i<9; i++) {
for(j=0; j<9; j++)
printf("%d",suduku[i][j]);
printf("\n");
}
}
if(isdone) return ;//当输出完成后结束函数 .
完整代码如下:
#include<stdio.h>
#include<string.h>
void Dfs(int x,int y);
void Getsuduku();
int suduku[9][10]; //存放数独
int H[9][10]; //标记是否在第 i行出现过
int L[9][10]; //标记是否在第 i 列出现过
int S[9][10]; //标记是否在第 i个小方块出现过
int isdone;
int main() {
int T;
scanf("%d",&T);
while(T--) {
memset(suduku,0,sizeof(suduku));//初始化数组
memset(H,0,sizeof(H));
memset(L,0,sizeof(L));
memset(S,0,sizeof(S));
Getsuduku();
isdone=0;
Dfs(0,0);
}
return 0;
}
void Getsuduku() {
int i,j;
for(i=0; i<9; i++) {
char temp[10];
scanf("%s",temp);
for(j=0; j<9; j++) {
suduku[i][j]=temp[j]-'0'; //转化为数字
if(suduku[i][j]) {
int k=i/3*3+j/3; //求出此时在第几个小方块里
H[i][suduku[i][j]]=1;// 将suduku[i][j]出现在i行进行标记
L[j][suduku[i][j]]=1;// 将suduku[i][j]出现在j列进行标记
S[k][suduku[i][j]]=1;// 将suduku[i][j]出现在第k个方块中标记
}
}
}
}
void Dfs(int x,int y) { //遍历每一点.
if(x==9) {//当处于第九行时
isdone=1;
int i,j;
for(i=0; i<9; i++) {
for(j=0; j<9; j++)
printf("%d",suduku[i][j]);
printf("\n");
}
}
if(isdone) return ;//当输出完成后结束函数 .
if(suduku[x][y]) {
if(y==8) Dfs(x+1,0);
else Dfs(x,y+1);
} else {
int num;
for(num=1; num<=9; num++) { //从 1 到 9 枚举数字
int k=x/3*3+y/3;//第k个小正方形.
if(!L[y][num]&&!H[x][num]&&!S[k][num]) { //如果该行该列该小正方形未曾填入数字,三项验证.
suduku[x][y]=num;//将num填入数独数组.
L[y][num]=1;//将已填入的信息更新
H[x][num]=1;
S[k][num]=1;
if(y==8) Dfs(x+1,0);
else Dfs(x,y+1);
suduku[x][y]=0;
L[y][num]=0;
H[x][num]=0;
S[k][num]=0;
}
}
}
}
运行结构如下:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)