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

题目描述

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

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

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

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

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

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

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

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

样例

输入样例:
...............293.5692............6.1745................
........8.4............5.1.................................7.4........
end
输出样例:

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

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

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

 //找到可选方案数最少的空格
int minv = ;
int x, y;
for(int i = ;i < N;i++)
for(int j = ;j < N;j++)
if (str[i*+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

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

 #include <iostream>
#include <algorithm>
#include <set> using namespace std; const int N = ; int row[N], col[N],cell[][]; char str[]; int ones[ << N],map[<<N]; inline int lowbit(int x) {
return x & -x;
} void init()
{
for (int i = ; i < N; i++) row[i] = col[i] = ( << N) - ;
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
cell[i][j] = ( << N) - ;
} inline int get(int x, int y)
{
return row[x] & col[y] & cell[x / ][y / ]; } bool dfs(int cnt)
{
if (!cnt) return true; //找到可选方案数最少的空格
int minv = ;
int x, y;
for(int i = ;i < N;i++)
for(int j = ;j < N;j++)
if (str[i*+j] == '.') {
int t = ones[get(i, j)];
if (t < minv) {
minv = t;
x = i, y = j;
}
} for (int i = get(x, y); i; i -= lowbit(i)) {
int t = map[lowbit(i)]; //修改状态
row[x] -= << t;
col[y] -= << t;
cell[x / ][y / ] -= << t;
str[x * + y] = '' + t;
if (dfs(cnt - )) return true; //回复现场
row[x] += << t;
col[y] += << t;
cell[x / ][y / ] += << t;
str[x * + y] = '.';
} return false;
} int main()
{
for (int i = ; i < N; i++) map[ << i] = i;
for (int i = ; i < << N; i++) {
int s = ;
for(int j = i; j;j -= lowbit(j)) s++;
ones[i] = s; //i的二进制表示中有s个1
} while (cin >> str, str[] != 'e') {
init();
int cnt = ;
for(int i =,k = ;i < N;i++)
for(int j = ; j < N;j++,k++)
if (str[k] != '.') {
int t = str[k] - '';
row[i] -= << t;
col[j] -= << t;
cell[i / ][j / ] -= << t;
}
else {
cnt++;
} dfs(cnt);
cout << str << endl;
} return ; } 作者:defddr
链接:https://www.acwing.com/solution/AcWing/content/2294/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 // 11111111.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// #include <iostream>
#include <map>
#include <vector>
#include <string>
#include <stdio.h> using namespace std; /*
.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
*/ const int N = ; int map1[ << N];
int Xarr[N];
int Yarr[N];
int SameXYArr[N / ][N / ]; int ones[ << N], map[ << N]; char str[]; void Init()
{
for (int i = ; i < N; i++) {
Xarr[i] = ( << N) - ;
Yarr[i] = ( << N) - ;
map1[ << i] = i;
} for (int i = ; i < N / ; i++) {
for (int j = ; j < N / ; j++) {
SameXYArr[i][j] = ( << N) - ;
}
}
} inline int lowbit(int x) {
return x & -x;
} inline int get(int x, int y)
{
return Xarr[x] & Yarr[y] & SameXYArr[x / ][y / ];
} bool Dfs(int count, char str[])
{
if (!count) return true; int minv = ;
int minx = -; int miny = -; for (int x = ; x < ; x++) {
for (int y = ; y < ; y++)
{
if (str[x * + y] == '.') {
int t = ones[get(x,y)]; if (t < minv) {
minv = t;
minx = x;
miny = y;
}
}
}
} if ( == minv)
return false; int tryNums = get(minx, miny); while (tryNums != ) {
int trynum = map1[lowbit(tryNums)]; Xarr[minx] -= << trynum;
Yarr[miny] -= << trynum;
SameXYArr[minx / ][miny / ] -= << trynum;
str[minx * + miny] = '' + trynum; if (Dfs(count - , str)) return true; //回复现场
Xarr[minx] += << trynum;
Yarr[miny] += << trynum;
SameXYArr[minx / ][miny / ] += << trynum;
str[minx * + miny] = '.'; tryNums -= lowbit(tryNums);
} return false;
} void Do(char str[])
{
Init();
int count = ;
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
if (str[i * + j] != '.') {
int idx = << (str[i * + j] - '');
Xarr[i] -= idx;
Yarr[j] -= idx;
SameXYArr[i / ][j / ] -= idx;
}
else {
count++;
}
}
} Dfs(count, str);
cout << str << endl; return;
} int main()
{
ios::sync_with_stdio(false); for (int i = ; i < N; i++) map1[ << i] = i;
for (int i = ; i < << N; i++) {
int s = ;
for (int j = i; j; j -= lowbit(j)) s++;
ones[i] = s; //i的二进制表示中有s个1 } while (cin >> str, str[] != 'e') {
//s = ".2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534."; Do(str);
} }

AcWing 166. 数独的更多相关文章

  1. 166. 数独 dancing links 方法

    dfs硬怼通过数独 N皇后的代码后 想学习下新的数据结构和算法来解决这类覆盖问题 习题练习 https://www.acwing.com/problem/content/168/ 数独 https:/ ...

  2. Swift数独游戏优化——C++与OC混编、plist自动生成

    一.为什么要C++与OC混编? 在我之前的数独游戏中涉及到的数独游戏生成算法是参考的网上其他人的算法,是利用C++来实现的.   但是在我的例子中我发现这样存在一定的局限性: 1.我是利用Termin ...

  3. iOS开发 Swift开发数独游戏(二)数独题目的生成

    一.Plist文件结构设计 由于要预先生成数独题目的文件,我自然而然想到用plist存取. 我用Xcode建了几个plist文件来熟悉这种文件使用的结构后设计了如下结构: 为区分难度(后来了解到挖空数 ...

  4. iOS开发 Swift开发数独游戏(四) 游戏界面的界面与逻辑

    一.游戏界面涉及到的功能点 1)数独格子的建模 (1)绘制数独格子要考虑到标记功能 所以要在每个格子内预先塞入9个标记数字,仅数独格子算下来就有9*9*9=729个格子且存在大量嵌套(这导致我在操作S ...

  5. LintCode389.判断数独是否合法

    LintCode简单题:判断数独是否合法 问题描述: 请判定一个数独是否有效. 该数独可能只填充了部分数字,其中缺少的数字用 . 表示. 注意事项: 一个合法的数独(仅部分填充)并不一定是可解的.我们 ...

  6. [LeetCode] Sudoku Solver 求解数独

    Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...

  7. [LeetCode] Valid Sudoku 验证数独

    Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be ...

  8. 数独 JAVA实现

    数独游戏的规则从很久之前就知道,但是一直都没怎么玩过,然后到了大学,大一下学期自己学dfs的时候,刚刚好碰到了一个数独的题目,做出来后,感觉还是挺有成就感的 然后大二学了JAVA,看了下那个一些有关于 ...

  9. 用C++实现的解数独(Sudoku)程序

    我是一个C++初学者,控制台实现了一个解数独的小程序. 代码如下: //"数独游戏"V1.0 //李国良于2016年11月11日编写完成 #include <iostream ...

随机推荐

  1. Java并发J.U.C学习总结

    转载自http://www.cnblogs.com/chenpi/结合自己理解稍有添加自己的理解 阅读目录 JSR 166及J.U.C Executor框架(线程池. Callable .Future ...

  2. visual studio 的快键键(持续更新)

    目录 1. CTRL+ Tab 2. Prop+ Tab 3. CTRL+. 4. 断点相关 5.快速搭建类的构造函数 6.查看需要引用的包 1. CTRL+ Tab 自动生成无参构造函数 2. Pr ...

  3. JS高级教程

    JS高级教程 JS高级教程

  4. maven配置多个镜像

    问题场景 1.国内访问maven默认远程中央镜像特别慢 2.用阿里的镜像替代远程中央镜像 3.大部分jar包都可以在阿里镜像中找到,部分jar包在阿里镜像中没有,需要单独配置镜像 解决方案 setti ...

  5. DBUtils的使用之查询的操作

    1.1 查询的代码实现1.1.1.1 查询一条记录 l 创建一个对象:Account l 查询代码实现 1.1.1.2 查询多条记录

  6. August 25th, 2019. Sunday, Week 35th.

    It's what you do next that counts, not what happens but what you decide to do about it. 重点不是发生了什么,而是 ...

  7. Spring源码解析-ioc容器的设计

    Spring源码解析-ioc容器的设计 1 IoC容器系列的设计:BeanFactory和ApplicatioContext 在Spring容器中,主要分为两个主要的容器系列,一个是实现BeanFac ...

  8. Java之通过接口获取数据并用JDBC存储到数据库中

    最近做数据同步功能,从接口获取数据然后存到数据库中以便后续对数据进行相关操作,下面就贴一下相关代码. import com.alibaba.fastjson.JSON; import com.alib ...

  9. 01-Nginx安装

    一.安装编译工具及库文件 yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel 二.首先安装PCRE PC ...

  10. vue安装遇到的5个报错小结

    前言 这篇博文不会教你怎么安装vue,但会告知安装过程中可能遇到的5个问题 2017年我写过一篇安装vue的博客,详情:https://www.cnblogs.com/tu-0718/p/752109 ...