题目地址 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. Elasticsearch各版本的MSI安装包和Kibana各版本的zip包(Windows)

    elastic各产品下载列表页:https://www.elastic.co/cn/downloads/ 打开Elasticsearch的下载页后看到的是当前最新版本的安装界面,现在最新的版本是7.4 ...

  2. ERROR 1366 (HY000): Incorrect string value: '\xE9\x83\x91\xE5\xB7\x9E' for column 'aa' at row 1 MySQL 字符集

    ERROR 1366 (HY000): Incorrect string value: '\xE9\x83\x91\xE5\xB7\x9E' for column 'aa' at row 1创建表之后 ...

  3. s3c2440裸机-清bss原理及实现

    1.清bss的引入(为什么要清bss) 我们先举个例子: #include "s3c2440_soc.h" #include "uart.h" char g_C ...

  4. VM虚拟机安装无法将值写入注册表.....请确认你是否有足够的权限访问该注册表项,或者与技术支持人员联系。

    解决方法: 关掉360安全卫士等软件再安装

  5. Node.js上传文件出现Unexpected field

    上传文件时,input框的name值要与node接口中single(' ')中的参数一致,否则会报"意外字段的错" 前端用的layui 后端node接口

  6. RabbitMQ学习笔记(八、RabbitMQ总结)

    1.什么是消息中间件 Message Queue Middleware,简称MQ,是一种利用高效可靠的消息传递机制进行与平台无关的数据交互的技术. 2.MQ的作用 异步:类似于短信业务,将需要发送的消 ...

  7. linux常用命令总结篇

    关于linux的一些基础命令,以前也学过,但是长时间不用还是感觉生疏了,所以记录下来以便后期温故知新. 1. cd:cd命令用来切换工作目录至dirname.cd ~ 进入用户主目录,cd - 进入之 ...

  8. pytorch 中改变tensor维度的几种操作

    具体示例如下,注意观察维度的变化 #coding=utf-8 import torch """改变tensor的形状的四种不同变化形式""" ...

  9. docker面试题和解答(一)

    什么Docker Docker是一个容器化平台,它以容器的形式将您的应用程序及其所有依赖项打包在一起,以确保您的应用程序在任何环境中无缝运行. Docker与虚拟机有何不同 Docker不是虚拟化方法 ...

  10. ASP.NET是什么?

    ASP.NET简介 简单来说,ASP.NET 是一个使用 HTML.CSS.JavaScript 和服务器脚本创建网页和网站的开发框架. 微软在2001年开发的第一个版本的ASP.NET,是一种建立在 ...