数独是一种传统益智游戏,你需要把一个 9×99×9 的数独补充完整,使得图中每行、每列、每个 3×33×3 的九宫格内数字 1∼91∼9 均恰好出现一次。
请编写一个程序填写数独。

输入格式

输入包含多组测试用例。
每个测试用例占一行,包含 8181 个字符,代表数独的 8181 个格内数据(顺序总体由上到下,同行由左到右)。
每个字符都是一个数字(1−91−9)或一个 .(表示尚未填充)。
您可以假设输入中的每个谜题都只有一个解决方案。
文件结尾处为包含单词 end 的单行,表示输入结束。

输出格式

每个测试用例,输出一行数据,代表填充完全后的数独。

输入样例:

4…..8.5.3……….7……2…..6…..8.4……1…….6.3.7.5..2…..1.4…… ……52..8.4……3…9…5.1…6..2..7……..3…..6…1……….7.4…….3. end

输出样例:

417369825632158947958724316825437169791586432346912758289643571573291684164875293 416837529982465371735129468571298643293746185864351297647913852359682714128574936


  1. #include <iostream>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. const int N = 9, M = 1 << N;
  6. int ones[M], map[M]; //ones表示二进制数有多少个1, map表示二进制数映射到十进制
  7. int row[N], col[N], cell[3][3]; //row, clo分别存每行每列的二进制数
  8. char str[100];
  9. void init() { //初始化每行每列的状态
  10. for (int i = 0; i < N; ++i) row[i] = col[i] = M - 1;
  11. for (int i = 0; i < 3; ++i)
  12. for (int j = 0; j < 3; ++j)
  13. cell[i][j] = M - 1;
  14. }
  15. //is_set表示是写还是擦除
  16. void draw(int x, int y, int t, bool is_set) {
  17. if (is_set) str[x * N + y] = t + '1';
  18. else str[x * N + y] = '.';
  19. int v = 1 << t;
  20. if (!is_set) v = -v;
  21. //对row,col,行列进行操作
  22. row[x] -= v;
  23. col[y] -= v;
  24. cell[x / 3][y / 3] -= v;
  25. }
  26. int lowbit(int x) // 返回末尾的1
  27. {
  28. return x & -x;
  29. }
  30. int get(int x, int y) { //返回可行的数字
  31. return row[x] & col[y] & cell[x / 3][y / 3];
  32. }
  33. bool dfs(int cnt) {
  34. if (!cnt) return true; //没有要填充的数字了
  35. //先找搜索状态小的
  36. int minv = 10;
  37. int x, y;
  38. for (int i = 0; i < N; ++i)
  39. for (int j = 0; j < N; ++j) {
  40. if (str[i * N + j] == '.') { //是'.'才搜索
  41. int state = get(i, j);
  42. if (ones[state] < minv) { //找填入少的进行搜索
  43. x = i; y = j;
  44. minv = ones[state];
  45. }
  46. }
  47. }
  48. int state = get(x, y);
  49. for (int i = state; i; i -= lowbit(i)) {
  50. int t = map[lowbit(i)];
  51. draw(x, y, t, true);
  52. if (dfs(cnt - 1)) return true;
  53. draw(x, y, t, false);
  54. }
  55. return false;
  56. }
  57. int main() {
  58. //预处理,打表
  59. for (int i = 0; i < N; ++i) map[1 << i] = i;
  60. for (int i = 0; i < M; ++i)
  61. for(int j = 0; j < N; ++j)
  62. ones[i] += i >> j & 1;
  63. while (cin >> str, str[0] != 'e') {
  64. init();
  65. int cnt = 0; //记录填充的个数
  66. for (int i = 0, k = 0; i < N; ++i)
  67. for (int j = 0; j < N; ++j, ++k) {
  68. //初始化,把已存在的数填进去
  69. if (str[k] != '.') {
  70. int t = str[k] - '1';
  71. draw(i, j, t, true);
  72. } else cnt++;
  73. }
  74. dfs(cnt);
  75. puts(str);
  76. }
  77. return 0;
  78. }