数独 九宫格 小学奥数

在处理到小学 如下 数独问题时

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;
}
发布了537 篇原创文章 · 获赞 529 · 访问量 44万+

猜你喜欢

转载自blog.csdn.net/mrcrack/article/details/104406276