题目地址 https://www.acwing.com/problem/content/description/168/

题目描述

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

请编写一个程序填写数独。

输入格式
输入包含多组测试用例。

每个测试用例占一行,包含81个字符,代表数独的81个格内数据(顺序总体由上到下,同行由左到右)。

每个字符都是一个数字(1-9)或一个”.”(表示尚未填充)。

您可以假设输入中的每个谜题都只有一个解决方案。

文件结尾处为包含单词“end”的单行,表示输入结束。

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

样例

输入样例:
.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
end
输出样例:
527389416819426735436751829375692184194538267268174593643217958951843672782965341
416837529982465371735129468571298643293746185864351297647913852359682714128574936

法1
时间卡的比较紧,搜索上做了许多优化

1 进行可填写数据的筛选.由于数独本身的性质,1~9同一数字不能在同一行 同一列 同一九宫格出现两次以上。
我开始计划是开一个 9*9的数组记录每个格子可能出现的数字.每次确认填写一个数字 就更新同行同列同九宫格里的记录
但是这样的话,每次填写一个数字及需要更新 一行9个 一列9个 和九宫格九格的数据。共27个数据。
YXC大佬的代码 使用的 行记录一个 列记录一个 九宫格记录一个 这样只需要更新三个数据即可

2 优化填写格子的策略,每个格子可填写的数据比较少的优先选取。 这也是剪枝的一种.
代码见

 //找到可选方案数最少的空格int minv = 10;int x, y;for(int i = 0;i < N;i++)for(int j = 0;j < N;j++)if (str[i*9+j] == '.') {int t = ones[get(i, j)];if (t < minv) {minv = t;x = i, y = j;}}

3 一些其他小技巧,使用位来记录该空格可填写那些数字
000000001 表示可填写1
000000010 表示可填写2
000000100 表示可填写3
000000101 表示可填写1和3
......
x = 000000111 表示可填写1 2 3。 如果我们当前选择填写2 那么只要 x - (1<<(2-1))就可以把填写2的表示去除了
代码里不是2-1 而是 可填写的数字的字母的实际值与 ‘1’的差值

4 判断是否是统一九宫格 采用 x/3==i/3 y/3 == j/3

还有其他一些小技巧 欢迎一起讨论

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <set>
  4
  5 using namespace std;
  6
  7 const int N = 9;
  8
  9 int row[N], col[N],cell[3][3];
 10
 11 char str[100];
 12
 13 int ones[1 << N],map[1<<N];
 14
 15 inline int lowbit(int x) {
 16     return x & -x;
 17 }
 18
 19 void init()
 20 {
 21     for (int i = 0; i < N; i++) row[i] = col[i] = (1 << N) - 1;
 22     for (int i = 0; i < 3; i++)
 23         for (int j = 0; j < 3; j++)
 24             cell[i][j] = (1 << N) - 1;
 25 }
 26
 27 inline int get(int x, int y)
 28 {
 29     return row[x] & col[y] & cell[x / 3][y / 3];
 30
 31 }
 32
 33 bool dfs(int cnt)
 34 {
 35     if (!cnt) return true;
 36
 37     //找到可选方案数最少的空格
 38     int minv = 10;
 39     int x, y;
 40     for(int i = 0;i < N;i++)
 41         for(int j = 0;j < N;j++)
 42             if (str[i*9+j] == '.') {
 43                 int t = ones[get(i, j)];
 44                 if (t < minv) {
 45                     minv = t;
 46                     x = i, y = j;
 47                 }
 48             }
 49
 50     for (int i = get(x, y); i; i -= lowbit(i)) {
 51         int t = map[lowbit(i)];
 52
 53         //修改状态
 54         row[x] -= 1 << t;
 55         col[y] -= 1 << t;
 56         cell[x / 3][y / 3] -= 1 << t;
 57         str[x * 9 + y] = '1' + t;
 58         if (dfs(cnt - 1)) return true;
 59
 60         //回复现场
 61         row[x] += 1 << t;
 62         col[y] += 1 << t;
 63         cell[x / 3][y / 3] += 1 << t;
 64         str[x * 9 + y] = '.';
 65     }
 66
 67
 68     return false;
 69 }
 70
 71 int main()
 72 {
 73     for (int i = 0; i < N; i++) map[1 << i] = i;
 74     for (int i = 0; i < 1 << N; i++) {
 75         int s = 0;
 76         for(int j = i; j;j -= lowbit(j)) s++;
 77         ones[i] = s; //i的二进制表示中有s个1
 78     }
 79
 80     while (cin >> str, str[0] != 'e') {
 81         init();
 82         int cnt = 0;
 83         for(int i =0,k = 0;i < N;i++)
 84             for(int j = 0; j < N;j++,k++)
 85                 if (str[k] != '.') {
 86                     int t = str[k] - '1';
 87                     row[i] -= 1 << t;
 88                     col[j] -= 1 << t;
 89                     cell[i / 3][j / 3] -= 1 << t;
 90                 }
 91                 else {
 92                     cnt++;
 93                 }
 94
 95         dfs(cnt);
 96         cout << str << endl;
 97     }
 98
 99     return 0;
100
101 }
102
103 作者:defddr
104 链接:https://www.acwing.com/solution/AcWing/content/2294/
105 来源:AcWing
106 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

View Code

  1 // 11111111.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
  2 //
  3
  4 #include <iostream>
  5 #include <map>
  6 #include <vector>
  7 #include <string>
  8 #include <stdio.h>
  9
 10 using namespace std;
 11
 12
 13
 14 /*
 15 .2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
 16 ......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
 17 end
 18 */
 19
 20
 21 const int N = 9;
 22
 23 int map1[1 << N];
 24 int Xarr[N];
 25 int Yarr[N];
 26 int SameXYArr[N / 3][N / 3];
 27
 28 int ones[1 << N], map[1 << N];
 29
 30 char str[100];
 31
 32 void Init()
 33 {
 34     for (int i = 0; i < N; i++) {
 35         Xarr[i] = (1 << N) - 1;
 36         Yarr[i] = (1 << N) - 1;
 37         map1[1 << i] = i;
 38     }
 39
 40     for (int i = 0; i < N / 3; i++) {
 41         for (int j = 0; j < N / 3; j++) {
 42             SameXYArr[i][j] = (1 << N) - 1;
 43         }
 44     }
 45 }
 46
 47 inline int lowbit(int x) {
 48     return x & -x;
 49 }
 50
 51 inline int get(int x, int y)
 52 {
 53          return Xarr[x] & Yarr[y] & SameXYArr[x / 3][y / 3];
 54 }
 55
 56 bool Dfs(int count, char str[])
 57 {
 58     if (!count) return true;
 59
 60     int minv = 10;
 61     int minx = -1; int miny = -1;
 62
 63     for (int x = 0; x < 9; x++) {
 64         for (int y = 0; y < 9; y++)
 65         {
 66             if (str[x * 9 + y] == '.') {
 67                 int t = ones[get(x,y)];
 68
 69                 if (t < minv) {
 70                     minv = t;
 71                     minx = x;
 72                     miny = y;
 73                 }
 74             }
 75         }
 76     }
 77
 78     if (0 == minv)
 79         return false;
 80
 81     int tryNums = get(minx, miny);
 82
 83
 84     while (tryNums != 0) {
 85         int trynum = map1[lowbit(tryNums)];
 86
 87         Xarr[minx] -= 1 << trynum;
 88         Yarr[miny] -= 1 << trynum;
 89         SameXYArr[minx / 3][miny / 3] -= 1 << trynum;
 90         str[minx * 9 + miny] = '1' + trynum;
 91
 92         if (Dfs(count - 1, str))  return true;
 93
 94         //回复现场
 95         Xarr[minx] += 1 << trynum;
 96         Yarr[miny] += 1 << trynum;
 97         SameXYArr[minx / 3][miny / 3] += 1 << trynum;
 98         str[minx * 9 + miny] = '.';
 99
100         tryNums -= lowbit(tryNums);
101     }
102
103     return false;
104 }
105
106 void Do(char str[])
107 {
108     Init();
109     int count = 0;
110     for (int i = 0; i < 9; i++) {
111         for (int j = 0; j < 9; j++) {
112             if (str[i * 9 + j] != '.') {
113                 int idx = 1 << (str[i * 9 + j] - '1');
114                 Xarr[i] -= idx;
115                 Yarr[j] -= idx;
116                 SameXYArr[i / 3][j / 3] -= idx;
117             }
118             else {
119                 count++;
120             }
121         }
122     }
123
124     Dfs(count, str);
125     cout << str << endl;
126
127     return;
128 }
129
130
131 int main()
132 {
133     ios::sync_with_stdio(false);
134
135     for (int i = 0; i < N; i++) map1[1 << i] = i;
136          for (int i = 0; i < 1 << N; i++) {
137                  int s = 0;
138                  for (int j = i; j; j -= lowbit(j)) s++;
139                  ones[i] = s; //i的二进制表示中有s个1
140
141     }
142
143         while (cin >> str, str[0] != 'e') {
144             //s = ".2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.";
145
146             Do(str);
147         }
148
149
150 }

View Code

转载于:https://www.cnblogs.com/itdef/p/10943355.html

AcWing 166. 数独相关推荐

  1. AcWing 166. 数独

    题意: 完成数独 思路: 看到题目,这肯定是搜索,但是试了一发普通的直接就超时了,肯定要加一些剪枝和优化,首先是位运算优化可以将每一行,每一列,每一个九宫格,都利用一个九位二进制数保存,当前还有哪些数 ...

  2. AcWing 166 数独

    题目描述: 数独是一种传统益智游戏,你需要把一个9 × 9的数独补充完整,使得图中每行.每列.每个3 × 3的九宫格内数字1~9均恰好出现一次. 请编写一个程序填写数独. 输入格式 输入包含多组测试用 ...

  3. 【acwing】166. 数独****(DFS)

    穿越隧道 如何能正确的搜出所有的方案 1.顺序 2.剪枝 搜索: 1.优化搜索顺序 大部分情况下,应优选搜索分支较少的节点 2.排除等效冗余 3.可行性剪枝 4.最优性剪枝 5.记忆化搜索(DP) 在 ...

  4. AcWing 1613. 数独简单版

    尽管说是数独简单版,可是对我来说却一点都不简单啊,这个很明显是用递归解决,这个递归又不同以往的递归,以往是一个节点为单位往下找,这个是一行为单位,从(0,0)到(9,9)顺序完全遍历一遍,我只涉及点为 ...

  5. AcWing 703. 数独检查

    **数独是一种流行的单人游戏. 目标是用数字填充9x9矩阵,使每列,每行和所有9个非重叠的3x3子矩阵包含从1到9的所有数字. 每个9x9矩阵在游戏开始时都会有部分数字已经给出,通常有一个独特的解决方 ...

  6. 【算法专题】数独问题详解

    数独问题详解 1. 概述 根据百度百科的描述:数独(shù dú)是源自18世纪瑞士的一种数学游戏.是一种运用纸.笔进行演算的逻辑游戏.玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并 ...

  7. 算法——AcWing算法提高课中代码和题解

    文章目录 第一章 动态规划 (完成情况:64/68) 数字三角形模型 最长上升子序列模型 背包模型 状态机模型 状态压缩DP 区间DP 树形DP 数位DP 单调队列优化DP 斜率优化DP 第二章 搜索 ...

  8. DFS剪枝优化 小猫爬山 数独

    DFS剪枝策略总结 优化搜索顺序 优先搜索分支数少(剩余选择少)的情况 排除等效冗余 若对顺序没有要求 可以将排列转化为组合 可行性剪枝 不合法的情况不进行搜索 最优化剪枝 若当前的"消耗& ...

  9. 0x22.搜索 - 深度优先搜索

    目录 一.DFS三个经典NPC问题 1.子集和问题 2.全排列问题 3.N皇后问题 luogu P1219 [USACO1.5]八皇后 Checker Challenge luogu P1562 还是 ...

  10. AcWing算法提高课笔记

    目录 Level2 1.动态规划--从集合角度考虑DP问题 1.1 数字三角形模型 1.1.1摘花生 1.1.2最低通行费 1.1.3方格取数 1.1.4传纸条 1.2 最长上升子序列模型 1.2.1 ...

最新文章

  1. 值得收藏!16段代码入门Python循环语句
  2. 开发者必读:计算机科学中的线性代数(附论文)
  3. boost线程之类成员函数
  4. 【bzoj2223】[Coci 2009]PATULJCI 主席树
  5. mysql centos 源码安装_centos7源码安装mysql8
  6. html+form+multipartform-data,表单 – 如何处理node.js中的multipart / form-data
  7. 华科考研834计算机网络,2018年华中科技大学834计算机专业基础综合 (模)...
  8. Spring 基础 用mock对Controller执行测试(系列号4)
  9. jsonView插件的安装方法
  10. 【知识整理】Nmap与Masscan
  11. deactivate不能关闭venv
  12. MySQL创建触发器的时候报1419错误( 1419 - You do not have the SUPER privilege and binary logging is enabled )
  13. 敏感性分析—Sobol
  14. 计算机的输入输出设备
  15. 名编辑电子杂志大师教程 | 书本打开密码
  16. 前端系列——与众不同的移动端底部固定栏 fixed、absolute 兼容 iOS 和 Android 方案...
  17. 跟着团子学SAP:LTMC进阶教程-用LTMOM调整标准模版(增加WBS层级字段示例)
  18. autocad命令、快捷键
  19. LaTeX: Missing } or { inserted. ^^I\For
  20. 企业安全中的用户与实体行为分析

热门文章

  1. 0024-CENTOS6.5安装CDH5.12.1(一)
  2. openJDK 源码下载
  3. [bzoj 1030][JSOI2007]文本生成器
  4. new对象后的代码块(匿名类)
  5. 无法在web 服务器上启动调试。打开的url的iis辅助进程当前没有运行
  6. [RMI TCP Connection(10.0.20.175:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Got ping response for
  7. Spark集群无法停止的原因分析和解决
  8. K8s(二):130 道 K8s/Docker 配套练习题,学+练结合,一次吃透
  9. Java 对象不使用时,为什么要赋值为 null?
  10. 循序渐进,一文详解微服务架构!