数独问题
题目描述
数独是一个非常有名的游戏。整个是一个9X9的大宫格,其中又被划分成9个3X3的小宫格。要求在每个小格中放入1-9中的某个数字。要求是:每行、每列、每个小宫格中数字不能重复。 现要求用计算机求解数独。(50分)
输入描述:
输入9行,每行为空格隔开的9个数字,为0的地方就是需要填充的数字。
输出描述:
输出九行,每行九个空格隔开的数字,为解出的答案。
基本思路
需要判断同一列同一行以及同一个九宫格的数值是否有重复,如果有冲突,则需要进行下一个数值的尝试。如果此次没有找到合适的数值,则需要作出栈操作,也就是回溯到上一级。在上一级的基础数值上再进行尝试,请勿再重新头开始。否则从1开始尝试,可以尝试出一个值;但是当处理下一个数值时发现有冲突,需要进行出栈操作。但此时又从1开始尝试,第一次尝试出的值还是之前那个值,此时处理下一个数值还是会发生冲突,也就是无法绕开出现矛盾的那个数值,从而造成了死循环,无法正常得到结果。
代码如下
#include <stdio.h> int main() { int test[9][9] = { 0,9,0,0,0,0,0,6,0, 8,0,1,0,0,0,5,0,9, 0,5,0,3,0,4,0,7,0, 0,0,8,0,7,0,9,0,0, 0,0,0,9,0,8,0,0,0, 0,0,6,0,2,0,7,0,0, 0,8,0,7,0,5,0,4,0, 2,0,5,0,0,0,8,0,7, 0,6,0,0,0,0,0,9,0, }; int i,j; int data[81][2] = {0}; //存储待处理的坐标二维数组,最多需要处理81个数据 int count = 0; //记录待处理的坐标,count表示需处理的坐标总数 for(i = 0; i < 9; i++){ for(j = 0; j < 9; j++){ if(test[i][j] == 0){ data[count][0] = i; data[count][1] = j; count++; } } } printf("count = %d\n",count); int okflag = 1; int nowstep = 0; //nowstep指示当前处理的待处理位置,nowstep==0为第一个,nowstep==count-1为最后一个 int n = 0; int si,sj; while(nowstep < count){ si = data[nowstep][0]; sj = data[nowstep][1]; // n = 1; n = test[si][sj]; //每次都从当前数继续,因为下面有test[si][sj] = n;一步,表示前面的已不合适,所以没必要再从1开始,会造成矛盾。 // okflag = 1; //冲突检测 while(n <= 9){ okflag = 1; //每一次标志需要重新设置 for(i = 0; i < 9; i++){ for(j = 0; j < 9; j++){ //冲突检测,此举代码表示当处于检测区域时,如果已经出现n,则表示存在冲突,此时需要进行下一步的检测 //而当检测区域既不处于同一行,也不属于同一列,同时也不属于同一个方格时 //s==i||t==j||((s/3)*3+t/3)==((i/3)*3+j/3)为0,也就没有检测的必要了,减少检测的次数。 //而当处于同一行列和一个方框时,必须要检测是否已经存在的数值n。 // if(i == si||j == sj||(((i/3)*3 + j/3)==((si/3)*3 + sj/3))&&test[i][j] == n){ if((i == si||j == sj||(((i/3)*3 + j/3)==((si/3)*3 + sj/3)))&&test[i][j] == n){ okflag = 0; //发生冲突,退出 break; } } if(okflag == 0){ //发生冲突,n++继续尝试 break; } } if(okflag == 1){ //当前值可用,退出n值尝试的while循环 break; } n++; } //如果标志为1,表示当前n值可以入栈,然后操作下一个为0的数独处 if(okflag == 1){ test[si][sj] = n; nowstep++; } //如果标志为0,表示当前n值有冲突,需要出栈处理,初始化当前冲突除为0,相当于没有检测此步 else if(okflag == 0){ test[si][sj] = 0; nowstep--; } } //结果输出 for(i = 0; i < 9; i++){ for(j = 0; j < 9; j++){ printf("%d,",test[i][j]); } printf("\n"); } return 0; }