AcWing 166. 数独
题目地址 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. 数独的更多相关文章
- 166. 数独 dancing links 方法
dfs硬怼通过数独 N皇后的代码后 想学习下新的数据结构和算法来解决这类覆盖问题 习题练习 https://www.acwing.com/problem/content/168/ 数独 https:/ ...
- Swift数独游戏优化——C++与OC混编、plist自动生成
一.为什么要C++与OC混编? 在我之前的数独游戏中涉及到的数独游戏生成算法是参考的网上其他人的算法,是利用C++来实现的. 但是在我的例子中我发现这样存在一定的局限性: 1.我是利用Termin ...
- iOS开发 Swift开发数独游戏(二)数独题目的生成
一.Plist文件结构设计 由于要预先生成数独题目的文件,我自然而然想到用plist存取. 我用Xcode建了几个plist文件来熟悉这种文件使用的结构后设计了如下结构: 为区分难度(后来了解到挖空数 ...
- iOS开发 Swift开发数独游戏(四) 游戏界面的界面与逻辑
一.游戏界面涉及到的功能点 1)数独格子的建模 (1)绘制数独格子要考虑到标记功能 所以要在每个格子内预先塞入9个标记数字,仅数独格子算下来就有9*9*9=729个格子且存在大量嵌套(这导致我在操作S ...
- LintCode389.判断数独是否合法
LintCode简单题:判断数独是否合法 问题描述: 请判定一个数独是否有效. 该数独可能只填充了部分数字,其中缺少的数字用 . 表示. 注意事项: 一个合法的数独(仅部分填充)并不一定是可解的.我们 ...
- [LeetCode] Sudoku Solver 求解数独
Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...
- [LeetCode] Valid Sudoku 验证数独
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be ...
- 数独 JAVA实现
数独游戏的规则从很久之前就知道,但是一直都没怎么玩过,然后到了大学,大一下学期自己学dfs的时候,刚刚好碰到了一个数独的题目,做出来后,感觉还是挺有成就感的 然后大二学了JAVA,看了下那个一些有关于 ...
- 用C++实现的解数独(Sudoku)程序
我是一个C++初学者,控制台实现了一个解数独的小程序. 代码如下: //"数独游戏"V1.0 //李国良于2016年11月11日编写完成 #include <iostream ...
随机推荐
- springboot中使用aop技术
aop是面向切面编程的意思,它可以需要先选择一些切入点,然后对这些切入点进行拦截,注入统一的代码逻辑,这也是解耦的一种方式,也是为了避免重复的代码,让开发人员把关注点放在业务上. 引用包 'org.s ...
- 松软科技web课堂:JavaScript 比较和逻辑运算符
JavaScript 比较和逻辑运算符 比较和逻辑运算符用于测试 true 或 false. 比较运算符 比较运算符在逻辑语句中使用,以判定变量或值是否相等. 我们给定 x = 5,下表中解释了比较运 ...
- 前端最佳实践——DOM操作
1.浏览器渲染原理 在讲DOM操作的最佳性能实践之前,先介绍下浏览器的基本渲染原理. 分为以下四个步骤: 解析HTML(HTML Parser) 构建DOM树(DOM Tree) 渲染树构建(Rend ...
- 快速搭建用于测试的rtsp协议网络流媒体数据服务
背景: 最近根据项目需求,在平台系统中加入了视频监控显示功能,但是限于没有提供真实可用的监控摄像头数据,通过EasyScreenLive快速搭建了一个rtsp的流媒体服务,下面将实现步骤分享给大家,为 ...
- jq实现回车键事件
我们写系统的时候常常因为要点击显得很麻烦,习惯了回车键完成一些东西. 接下来就直接上代码吧.jq实现回车键事件 keyDowm: () => { $("body").keyd ...
- 表单生成器(Form Builder)之伪造表单数据番外篇——随机车辆牌照
前几天记录了一下表单生成器(Form Builder)之表单数据存储结构mongodb篇,之后便想着伪造一些数据.为什么要伪造数据呢?说来惭愧,因为拖拉拽设计表单以及表单对应的列表的PC端和移动端该显 ...
- subprocess之check_out用法
在python3中使用subprocess的check_out方法时,因为该输出为byte类型,所以如果要查看具体的内容时需要进行转码,如果转码不对话,会影响内容输出的可读性,如下: #1,输出解码不 ...
- mysqlbinlog-Note
binlog_format = mixedlog-bin = /data/mysql/mysql-binexpire_logs_days = 7 #binlog过期清理时间max_binlog_siz ...
- Less(6)
1.先判断注入类型 (1)首先看到要求,要求传一个ID参数,并且要求是数字型的:?id=1 (2)再输入?id=1' (3)再输入?id=1 and 1=1 (4)再输入?id=1 and 1=2 ( ...
- Springboot关于tomcat容器配置、三大组件配置、拦截器配置
原文地址:http://www.javayihao.top/detail/172 1.tomcat配置 Springboot默认使用的就是嵌入式servlet容器即tomcat,对于web项目,如果使 ...