数独(一)
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个数独