在处理到小学 如下 数独问题时
Input1:
0 2 0 8 0 7 3 0 0
9 0 0 1 0 0 5 7 0
8 3 0 0 0 5 2 0 0
0 4 0 0 8 0 6 0 0
0 0 2 4 7 0 1 0 0
6 0 5 0 0 3 0 8 0
0 0 6 7 0 0 0 4 3
0 9 3 0 0 8 0 0 6
0 0 8 3 0 4 0 2 0
Input2:
0 0 0 1 6 0 0 0 0
0 0 3 0 0 9 0 0 4
7 0 0 0 0 0 8 2 0
0 8 0 7 0 0 0 0 0
9 0 0 0 0 0 0 0 5
0 0 0 0 0 1 0 4 0
0 4 5 0 0 0 0 0 6
8 0 0 5 0 0 1 0 0
0 0 0 0 3 2 0 0 0
Input3:
0 0 0 1 8 0 0 0 0
0 0 3 0 0 9 0 0 4
7 0 0 0 0 0 8 2 0
0 8 0 7 0 0 0 0 0
0 0 0 0 0 0 0 0 5
9 0 0 0 0 1 0 4 0
0 4 5 0 0 0 0 0 6
8 0 0 5 0 0 1 0 0
0 0 0 0 3 2 0 0 0
发现手算功力不够,也耗不起这个时间。
故决定编程解决,程序处理后,对应输出结果如下
Output1:
5 2 1 8 9 7 3 6 4
9 6 4 1 3 2 5 7 8
8 3 7 6 4 5 2 9 1
7 4 9 5 8 1 6 3 2
3 8 2 4 7 6 1 5 9
6 1 5 9 2 3 4 8 7
2 5 6 7 1 9 8 4 3
4 9 3 2 5 8 7 1 6
1 7 8 3 6 4 9 2 5
Output2:
4 2 8 1 6 7 5 3 9
5 1 3 2 8 9 7 6 4
7 6 9 4 5 3 8 2 1
6 8 4 7 2 5 9 1 3
9 7 1 3 4 6 2 8 5
3 5 2 8 9 1 6 4 7
2 4 5 9 1 8 3 7 6
8 3 6 5 7 4 1 9 2
1 9 7 6 3 2 4 5 8
Output3:
无解
打了一段时间的codeforces,发现码力渐涨,以下思路,代码全是独立完成,没有参考任何资料。
核心思路如下:
动手简单模拟,发现,格中某个数字是否能加入,要看,该格的行是否冲突,列是否冲突,小九宫格是否冲突。
//row[i][j] i行上是否存在数值j;col[i][j] i列上是否存在数值j;block[i][j] i块上是否存在数值j;
//block[i]对应小九宫格,共9个
一直有顾虑,每个格子都可能放1-9,每个格子有9种情况,那么总共有81个格子,那么就有9^81=1.97*10^77可能,那么dfs要超时。
其实呢,因为数独的约束,格子中放数字的可能,越到之后遇到的格子,越小,所有实际情况远远小于9^81=1.97*10^77,通常是九宫格初始给的数据越多,算法消耗的时间越小。
处理代码如下:
#include <stdio.h>
#define N 9
//row[i][j] i行上是否存在数值j;col[i][j] i列上是否存在数值j;block[i][j] i块上是否存在数值j;
//block[i]对应小九宫格,共9个
int a[N][N+1],row[N][N+1],col[N][N+1],block[N][N+1];//此处错写成int a[N][N],row[N][N],col[N][N],block[N][N];
void init(){
int i,j;
for(i=0;i<N;i++)
for(j=0;j<N;j++){
scanf("%d",&a[i][j]);//block的理解,建议拿出纸笔,研究小九宫格脚标规律
row[i][a[i][j]]=1,col[j][a[i][j]]=1,block[(i/3)*3+j/3][a[i][j]]=1;
}
}
void matrix(){
int i,j;
for(i=0;i<N;i++){
for(j=0;j<N;j++)
printf(" %d",a[i][j]);
printf("\n");
}
printf("\n");
}
void dfs(int r,int c){
int i;
if(r==N){//九宫格遍历完毕
matrix();//打印
return;
}
if(a[r][c]){
if(c==N-1)dfs(r+1,0);//处理到行末,下一行开始
else dfs(r,c+1);//同一行的下一列
}else{
for(i=1;i<=N;i++)
if(!row[r][i]&&!col[c][i]&&!block[(r/3)*3+c/3][i]){
row[r][i]=1,col[c][i]=1,block[(r/3)*3+c/3][i]=1,a[r][c]=i;
if(c==N-1)dfs(r+1,0);
else dfs(r,c+1);
row[r][i]=0,col[c][i]=0,block[(r/3)*3+c/3][i]=0,a[r][c]=0;//回溯
}
}
}
int main(){
init();
dfs(0,0);
return 0;
}