【原创】转载请注明出处。 【浙江大学 程序设计专题】

使用方法:按提示输入方式为9*9的矩阵,0表示未知数。

为解决这一问题,我们也尝试了两种方法,准确的说,是第一种方法太慢了,我们对它进行了优化。

方法一:
用最朴素的方法逐一枚举每一个格子,在某一个格子不能填入任何数字时回溯。
这个方法写法相对简单,但对于一些难以求解的情况,程序会非常慢,最慢的甚至无法在3秒内得出答案。如果每一个情况需要三秒钟来求解,那么要批量求解数独可能需要等好几分钟。
尽管我们将编译器的优化选项开到最高,一些情况仍需要1秒左右。

方法二:
模拟手算,当给定一道题目时,首先确定每个格子可以填那些数字,每次优先选择可选数字最少的格子。
此方法对于大多数数据能在0.1秒内求解。

 

方法一样例解释:绿色数字表示有多重可能的格子,红色数字表示唯一可能的格子,红色填充的格子表示无法填入数字。

[ C语言版 ] 数独计算器 [ 搜索剪枝法 ]

方法二样例:

[ C语言版 ] 数独计算器 [ 搜索剪枝法 ][ C语言版 ] 数独计算器 [ 搜索剪枝法 ]

方法一代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <time.h>
  5 #include "prnt_sudoku.h"
  6 
  7 /*Sudoku save in array Map, index counts from 0.*/
  8 int    Map[9][9],cnt;
  9 /*R<->Row  B<->Block  C<->Column*/
 10 int    R[11][11],B[11][11],C[11][11];
 11 /*characters on the left and right of output-numbers.*/
 12 /*this will make user know which numbers are given at first.*/
 13 char    C1[9][9],C2[9][9];
 14 
 15 int    Dfs(const int x,const int y)
 16 {
 17     if(x==9)
 18     {
 19         printf("\n\n\tSolution #%d:  \n\n",++cnt);
 20         Print(Map,C1,C2);
 21         /*when there are too many solutions return 1*/
 22         /*and the whole Search algorithm will stop*/
 23         if(cnt==5000) return 1;
 24         return 0;
 25     }
 26 
 27     if(Map[x][y]) { return Dfs(x+(y+1)/9,(y+1)%9); }
 28     /*if (x,y) is known, then fill the next one.*/
 29 
 30     int i;
 31     for(i=1;i<=9;++i)
 32     {
 33         /*Check if setting i in blank(x,y) is proper.*/
 34         if(R[x][i] || C[y][i] || B[x/3*3+y/3][i])continue;
 35 
 36         /*update arrays*/
 37         Map[x][y]=i;
 38         R[x][i]=1; C[y][i]=1; B[x/3*3+y/3][i]=1;
 39 
 40         if(Dfs(x+(y+1)/9,(y+1)%9)) return 1;
 41         /*this expression will fill blanks from the left-up one to */
 42         /*  the right-down one automaticly.*/
 43 
 44         /*undo*/
 45         R[x][i]=0; C[y][i]=0; B[x/3*3+y/3][i]=0;
 46         Map[x][y]=0;
 47     }
 48     return 0;
 49 }
 50 
 51 
 52 int main()
 53 {
 54     int op,T=0;
 55     system("cls");
 56     printf("Choose input/output way(1.Keyboard/2.File):  ");
 57     while(1)/*until receiving an expected input.*/
 58     {
 59         scanf("%d",&op);
 60         if(op==1)break;
 61         if(op==2)/*file input*/
 62         {
 63             char File_Name[110];
 64             printf("Please input File_Name:  ");
 65             scanf("%s",File_Name);
 66             printf("\n\tResult Will Save to Result.txt\n\n");
 67             printf("\tCalculating....\n\n");
 68             freopen(File_Name,"r",stdin);
 69             freopen("Result.txt","w",stdout);/*answer file is "Result.txt" */
 70             break;
 71         }
 72     }
 73 
 74     while(1)/*Support multi-set test, read to EOF.*/
 75     {
 76         /*Initialize*/
 77         memset(R,0,sizeof(R));
 78         memset(C,0,sizeof(C));
 79         memset(B,0,sizeof(B));
 80         memset(Map,0,sizeof(Map));
 81         cnt=0;
 82         if(op==1)printf("Please Input 9*9 matrix(0 for space):\n");
 83         int i,j,data;
 84         /*Read until EOF*/
 85         for(i=0;i<9;++i) for(j=0;j<9;++j)
 86         {
 87             if(!(~scanf("%1d",&data)))
 88             {
 89                 if(op==1)system("pause");
 90                 fclose(stdin);
 91                 return 0;
 92             }
 93             Map[i][j]=data;
 94             R[i][data]++;
 95             C[j][data]++;
 96             B[i/3*3+j/3][data]++;
 97         }
 98 
 99         printf("Test Case #%d: ",++T);
100         int f=0;/*Check if the sudoku is valid.*/
101         for(i=0;i<9;++i) for(j=1;j<=9;++j)
102             if(R[i][j]>1|| C[i][j]>1 || B[i][j]>1) f=1;
103         if(f)/*Invalid input*/
104         {
105             fprintf(stderr,"\n\t\tError in Test Case #%d: ",T);
106             fprintf(stderr,"Invalid Input.\n");
107             printf("\n\n\tFiled: No Solution Found!\n\n");
108             continue;
109         }
110 
111         /*Mark the known grids.*/
112         for(i=0;i<9;++i) for(j=0;j<9;++j)
113                 if(Map[i][j])C1[i][j]='[',C2[i][j]=']';
114                 else C1[i][j]=C2[i][j]=' ';
115 
116         int t1=clock();/*Timer*/
117         if(Dfs(0,0))
118             /*In case of costing too much time and disk storage,*/
119             /*Dfs(int,int) will find at most 5000 kinds of solution.*/
120         {
121             fprintf(stderr,"\n\t\tError in Test Case #%d: ",T);
122             fprintf(stderr,"Too much solution! Calculation has broken.\n");
123         }
124 
125         /*output the time*/
126         if(cnt==0) printf("\n\n\tFiled: No Solution Found!\n\n");
127         else printf("\n\n\t%d Solution Found In %ldms.\n\n",cnt,1000*(clock()-t1)/CLOCKS_PER_SEC);
128     }
129 
130     return 0;
131 }
View Code

相关文章:

  • 2021-11-21
  • 2021-12-11
  • 2022-02-14
  • 2021-05-25
  • 2022-12-23
  • 2022-12-23
  • 2022-01-23
猜你喜欢
  • 2022-12-23
  • 2021-06-08
  • 2022-12-23
  • 2022-01-20
  • 2021-12-28
  • 2021-08-27
  • 2021-05-18
相关资源
相似解决方案