数独(一)

半城伤御伤魂 提交于 2021-02-12 09:05:32

Github地址:https://github.com/cfafa2018/SudokuProject

思路:

根据题目要求,摘取出一些需要解决的问题,差不多也就是整体的解题思路。

代码分成了两大块,生成数独和解数独部分,还有一些小的函数。

(1)命令行中使用 -c和-s,识别并根据命令生成或读取相应的文件。

    用ofstream和C语言里面的fopen。对于-c和-s以及一些错误的输入,例如:-c ab 进行处理,提示 Wrong input。利用main函数里的argc和argv两个参数解决。

(2)生成数独。

    根据要求,数独左上角的第一个数应该为 (0 + 8)% 9 + 1 = 9,后面8个位置用剩下的8个数进行全排列。然后下面的8行可以分别通过第一行右移得到。(借鉴了同学的思路)这里采用C++实现。

 1 if(AllisNum(argv[2])){
 2             int shudu[9][9]={0},arr[]={1,2,3,4,5,6,7,8};
 3             shudu[0][0] = 9;//数独第一个数字为9
 4             for(int i = 0; i < atoi(argv[2]); i ++){
 5                 next_permutation(arr, arr+8);
 6                 for(int j =0; j < 8; j ++){//将arr数组里排列好的数赋给shudu第一行
 7                     shudu[0][j+1] = arr[j];
 8                 }
 9                 int num[9]={0,3,6,1,4,7,2,5,8};
10                 int temp[9];
11                 memcpy(&temp, &shudu[0], sizeof(shudu[0]));
12                 for(int j=0; j < 9; j ++){//通过第一行进行下面8列的移数
13                     int n =9;
14                     RightShift(shudu[0], n, num[j]);
15                     for(int k = 0; k < 8; k ++){//输出数据
16                         write<<"shudu[0][k] ";
17                     }
18                     write<<"shudu[0][k]\n";
19                     memcpy(&shudu[0], &temp, sizeof(temp));
20                 }
21                 write<<"\n";
22             }
23         }
24         else write<<"Wrong input\n";
25     }

 

(3)解数独。

  根据数独的求解规则,可以知道,每一小格要求填上1~9中的一个数,而且要求在同一行,同一列,以及包括这一小格在内的所有的3X3的九宫格都不在包含这个数。按照求解规则进行填数,所有小格循环进行。如果遇到无解的小格,则回到上一个点,还不行就一直回溯,直到得到解为止。下面用回溯法来进行求解。

 1 void backtrace(int count){
 2     if(count == 81){
 3         for(int i = 0; i < 9; ++i){
 4             for(int j =  0; j < 8; ++j){
 5                 
 6                 output<<map[i][j];
 7                 output<<" ";
 8             }
 9             output<<map[i][8]<<endl;
10         }
11         output<<"\n";
12         return;
13     }
14     int row = count / 9;
15     int col = count % 9;
16     if(map[row][col] == 0){
17         for(int i = 1; i <= 9; ++i){
18             map[row][col] = i;//赋值
19             if(isPlace(count)){//可以放
20                 backtrace(count+1);//进入下一层
21             }
22         }
23         map[row][col] = 0;//回溯
24     }
25     else{
26         backtrace(count+1);
27     }
28 }

 

(4) 性能分析。

生成1000个数独

解100个数独

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!