递归题目练习---数独问题

简介: 递归题目练习---数独问题

数独问题


题目描述

数独是一个非常有名的游戏。整个是一个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;
}

image.png

目录
相关文章
|
6月前
|
索引
力扣---最长回文子串(动态规划)
力扣---最长回文子串(动态规划)
|
算法
LeetCode 37 解数独 循环+回溯算法
LeetCode 37 解数独 循环+回溯算法
59 0
剑指offer_递归与循环---跳台阶
剑指offer_递归与循环---跳台阶
61 0
剑指offer_递归与循环---矩形覆盖
剑指offer_递归与循环---矩形覆盖
81 0
剑指offer_递归与循环---斐波那契数列
剑指offer_递归与循环---斐波那契数列
63 0
|
机器学习/深度学习
剑指offer_递归与循环---变态跳台阶
剑指offer_递归与循环---变态跳台阶
63 0
剑指offer_递归与循环---扑克牌顺子
剑指offer_递归与循环---扑克牌顺子
50 0
初学算法之递归---爬楼梯
初学算法之递归---爬楼梯
|
算法
递归题目练习---N皇后问题
递归题目练习---N皇后问题
109 0
递归题目练习---N皇后问题
递归题目练习---扭蛋机
递归题目练习---扭蛋机
94 0
递归题目练习---扭蛋机