题目地址 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. 爬虫(二):抓包工具Fiddler

    1. 抓包工具Fiddler 1.1 Fiddler下载与安装 最简单的方法,打开百度,搜索fiddler下载. 下载完毕解压即可,此版本为绿色版. 点击这个即可运行抓包软件. 1.2 Fiddler ...

  2. MySQL的表定义语法

    表定义 只有成功创建数据库后,才能创建数据表,数据表是字段的集合,在表中数据按行和列的格式存储 创建表 MySQL 使用 CREATE TABLE 创建表.其中有多个选择,主要由表创建定义(creat ...

  3. [转载]——Automatic Tuning of Undo_retention Causes Space Problems (文档 ID 420525.1)

    Automatic Tuning of Undo_retention Causes Space Problems (文档 ID 420525.1) 转到底部 In this Document   Sy ...

  4. RMAN RECOVER TABLE 功能是 Oracle Database 12c 的新增功能 (Doc ID 1521524.1)

    RMAN RECOVER TABLE Feature New to Oracle Database 12c (Doc ID 1521524.1) APPLIES TO: Oracle Database ...

  5. windows命令行pip报错解决的方法

    今天在新电脑安装python,发现pip无效了,于是乎百度了很多方法,发现原因是pip升级导致的 解决办法,卸载pip重新安装 可以首先执行  python -m ensurepip  然后执行 py ...

  6. 剑指Offer-45.扑克牌顺子(C++/Java)

    题目: LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定 ...

  7. [译]Vulkan教程(21)顶点input描述

    [译]Vulkan教程(21)顶点input描述 Vertex input description 顶点input描述 Introduction 入门 In the next few chapters ...

  8. vuetify,vux,Mint UI 等框架的选择

    vuetify: https://vuetifyjs.com/zh-Hans/getting-started/quick-start NutUI:https://github.com/jdf2e/nu ...

  9. jupyter notebook改变行间图片大小

    jupyter notebook使用起来代码效果很直接,这是我最喜欢的一点,但是主题单一,后来改了一下主题.也可以接受了,但是还有一个问题是显示图片太小我们可以用两个方法来改变它. 一.可以通过rcP ...

  10. C# show Environment property info name and value retrieve, Maximize the Console Window based on window resolution

    using System.Reflection; static void ShowEnvironmentInfoDemo() { Type type = typeof(Environment); Pr ...