cmembd

  《编程之美》书上并没有这一节,而是我根据“构造数独”一节推广而来的。上一篇我用矩阵的初等变换来构造数独,这一篇我就用DFS(其实我觉得叫递归+回溯更贴切)来求解数独

  具体的步骤我就不啰嗦了,不了解的可以参考任何一本算法书或数据结构的书。递归求解数独并不像网上一些说人的那么慢(一个比较难的数独也是瞬间就解出来了),更不会有栈溢出,处理不当就另当别论。

  这个程序采用文件输入,输入的数据格式为:

800000000
003600000
070090200
050007000
000045700
000100030
001000068
008500010
090000400

其中0表示要填的空。为了操作方便我用一维数组来表示二维数组。

  最后要说明的是,当所有都是要填的空时就相当于构造数独了。当然,这个程序只能构造出一种数独,要使每次构造出不同的数独就需要在算法中加入随机因子了。

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <memory.h>
  4 #include <malloc.h>
  5 
  6 void Print(char *grid);
  7 int Next(int index);
  8 char *GetAllowable(int index, int *count);
  9 void Solve(int index);
 10 bool completed = false; //标记是否完成
 11 bool nosolution = false; //标记是否无解
 12 int startIndex = 0;
 13 char solution[81]; //保存数独
 14 int main(int argc, char *argv[])
 15 {
 16     FILE *file;
 17     char ch;
 18     int i = 0;
 19 
 20     //从文件读入
 21     if ((file = fopen("problem.txt", "r")) == NULL)
 22     {
 23         exit(0);
 24     }
 25 
 26     while ((ch = fgetc(file)) != EOF)
 27     {
 28         if (ch != \'\n\')
 29         {
 30             *(solution + i) = ch;
 31             i++;
 32         }
 33     }
 34 
 35     fclose(file);
 36     puts("题目:");
 37     Print(solution);
 38     startIndex = Next(-1);
 39     Solve(startIndex);
 40 
 41     if (!nosolution) //有解
 42     {
 43         puts("\n解答:");
 44         Print(solution);
 45     }
 46     else
 47     {
 48         puts("无解!");
 49     }
 50 
 51     puts("");
 52     system("pause");
 53     return 0;
 54 }
 55 //输出数独
 56 void Print(char *grid)
 57 {
 58     for (int i = 0; i < 81; ++i)
 59     {
 60         printf("%2c", grid[i] == \'0\' ? \'_\' : grid[i]);
 61 
 62         if (i % 9 == 8)
 63         {
 64             printf("\n");
 65         }
 66     }
 67 }
 68 //返回所有在index位置请允许的数字,count为总数
 69 char *GetAllowable(int index, int *count)
 70 {
 71     int r = index / 9; //
 72     int c = index % 9; //
 73     bool f[10];
 74 
 75     for (int i = 1; i < 10; ++i)
 76     {
 77         f[i] = true;
 78     }
 79 
 80     for (int i = 0; i < 9; ++i)
 81     {
 82         f[solution[r * 9 + i] - \'0\'] = false; //
 83         f[solution[9 * i + c] - \'0\'] = false; //
 84         f[solution[(r / 3 * 3 + i / 3) * 9 + c / 3 * 3 + i % 3] - \'0\'] = false; //小九宫格
 85     }
 86 
 87     int n = 0;
 88 
 89     for (int i = 1; i < 10; ++i)
 90     {
 91         if (f[i])
 92         {
 93             n++;
 94         }
 95     }
 96 
 97     char *v = NULL;
 98 
 99     if (n > 0)
100     {
101         v = (char *)malloc(sizeof(char) * n);
102 
103         if (v == NULL)
104         {
105             exit(0);
106         }
107 
108         for (int i = 1, j = 0; i < 10; ++i)
109             if (f[i])
110             {
111                 v[j++] = i + \'0\';
112             }
113     }
114 
115     *count = n;
116     return v;
117 }
118 //求解主函数
119 void Solve(int index)
120 {
121     int n, next;
122     char *v = GetAllowable(index, &n);
123 
124     if (n == 0)
125     {
126         return;
127     }
128 
129     for (int i = 0; i < n; ++i)
130     {
131         solution[index] = v[i];
132 
133         if ((next = Next(index)) == 81) //完成
134         {
135             completed = true;
136         }
137         else
138         {
139             Solve(next); //递归
140         }
141 
142         if (completed == true)
143         {
144             free(v);
145             return;
146         }
147     }
148 
149     free(v);
150     solution[index] = \'0\';
151 
152     if (index == startIndex) //无解
153     {
154         nosolution = true;
155     }
156 }
157 //找下一个要填的空格
158 int Next(int index)
159 {
160     while (++index < 81 && solution[index] != \'0\');
161 
162     return index;
163 }
代码

 

分类:

技术点:

相关文章:

  • 2022-01-18
  • 2022-01-27
  • 2021-04-11
  • 2022-01-24
  • 2022-01-23
猜你喜欢
  • 2021-12-09
  • 2021-12-09
  • 2021-11-03
  • 2021-10-15
  • 2021-12-09
  • 2020-10-28
  • 2021-11-03
相关资源
相似解决方案