对于 9∗99*99∗9 大小的数独游戏,我们可以使用回溯法求得其正确的解,但是,一般的回溯法实现这个过程保证不了时间复杂度,所以我们可以利用二进制压缩的方法来优化其过程。

具体思路如下:

明确数独的约束:

  • 相同一行不能出现重复的数
  • 相同一列不能出现重复的数
  • 同一宫内不能出现重复的数

定义row[i]row[i]row[i]数组代表,第i,ji,ji,j位置,在 iii 行哪些数被占用,用二进制 111 表示没有被占用,000 表示被占用那么最开始 row[i]row[i]row[i] = 111111111111111111111111111,表示行没有数被占用。

定义col[j]col[j]col[j]数组代表,第i,ji,ji,j位置,第 jjj 列哪些数被占用,用二进制 111 表示没有被占用,000 表示被占用,那么最开始col[i]col[i]col[i] = 111111111111111111111111111,表示列没有数被占用。

定义cell[i/3][j/3]cell[i/3][j/3]cell[i/3][j/3]数组代表,第 i,ji,ji,j 格所在的宫中那些数被占用,用二进制 111 表示没有被占用,000 表示被占用,那么最开始cell[i/3][j/3]cell[i/3][j/3]cell[i/3][j/3] = 111111111111111111111111111,表示宫中没有数被占用。

然后我们需要初始化上面三个数组,因为一开始的数独游戏位置被一些数占用了,那么这些数的位置就会影响row[i],col[j],cell[i][j]row[i],col[j],cell[i][j]row[i],col[j],cell[i][j]的二进制数,我们需要把相应的数,在二进制数的响应位改变成0,表示这个数在此列或行或宫被占用了。

然后我们利用位运算&对三个数组进行&,就可以得到三个数组都没有被占用的数,然后从其中挑选数,进行回溯法即可得到数独的解。

注意要熟悉:lowbit()lowbit()lowbit()的用法,是取二进制数第一次出现111时的大小,例如100100100100100100,这个数的lowbit()lowbit()lowbit()就是100100100,在这个程序中他用来取&后的数字的二进制可用数是多少,这个可用数我们也提前预处理,映射到了map[]map[]map[]数组里,然后这个还有一个贪心策略,即当可用数越少答案就越确定,我们用ones[]ones[]ones[]数组记录一下所有可出现状态的1的数量,1的数量少代表当前位置越确定,这个可以对程序执行很大的优化。

下面以一个数独游戏为例:
被解决的数独游戏:

程序跑出的解:
输入的时候空位置用.代替即可


可执行代码:

#include <algorithm>
#include <iostream>
using namespace std;
const int N = 9;
int row[N], col[N], cell[3][3], ones[1 << N], map[1 << N], cnt;
char s[N][N];
inline int lowbit(int x) {return (x & -x);
}
inline void init() {for (int i = 0; i < N; i++)row[i] = col[i] = (1 << N) - 1;for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++)cell[i][j] = (1 << N) - 1;
}
inline int get(int x, int y) {return row[x] & col[y] & cell[x / 3][y / 3];
}
bool dfs(int cnt) {if (!cnt)return true;int x, y, mav = 10;for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {if (s[i][j] == '.') {int t = ones[get(i, j)];if (mav > t) {mav = t;x = i, y = j;}}}}for (int i = get(x, y); i; i -= lowbit(i)) {int t = map[lowbit(i)];row[x] -= 1 << t;col[y] -= 1 << t;cell[x / 3][y / 3] -= 1 << t;s[x][y] = '1' + t;if (dfs(cnt - 1))return true;row[x] += 1 << t;col[y] += 1 << t;cell[x / 3][y / 3] += 1 << t;s[x][y] = '.';}return false;
}
int main() {for (int i = 0; i < N; i++)map[1 << i] = i;for (int i = 0; i < (1 << N); i++) {int k = 0;for (int j = i; j; j -= lowbit(j)) {k++;}ones[i] = k;}while (true) {for (int i = 0; i < N; i++)cin >> s[i];init();cnt = 0;for (int i = 0; i < 9; i++) {for (int j = 0; j < 9; j++) {if (s[i][j] != '.') {int t = s[i][j] - '1';row[i] -= 1 << t;col[j] -= 1 << t;cell[i / 3][j / 3] -= 1 << t;} else {cnt++;}}}dfs(cnt);for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {cout << s[i][j] << ' ';}cout << endl;}}return 0;
}

利用计算机程序快速得到9*9大小数独的解法相关推荐

  1. 利用 画图 快速给图片添加文字

    利用 画图 快速给图片添加文字 有时候我们需要给某些图片上添加文字,大多数人可能第一时间会想到PS,其实如果我们只是添加文字的话,Windows下的 画图 工具也是非常不错的选择. 我们选择要编辑的图 ...

  2. 如何利用CCleaner快速查找重复文件?

    一般的电脑随着时间的推移磁盘里面会有多份的重复文件,这些重复项会占用硬盘驱动器上面的空间,并且很难追踪到文件的位置以及更改的文件.但是CCleaner却轻松的解决了这个问题,那么如何利用CCleane ...

  3. 利用PS快速抠图的5个超实用技巧

    利用PS快速抠图的5个超实用技巧 抠图是图像处理中最常做的操作之一,也是photoshop中最为常用的技术之一.抠图其实并不难,只要你有足够的耐心和细心,只须掌握PS中一些基础知识就能完美的抠出图片. ...

  4. Unreal Engin_画廊制作笔记_001<设计草图,利用BSP快速搭建简单场景>

    001设计草图,利用BSP快速搭建简单场景 本笔记开始记录所学的知识点以及细节操作等,分享下自己学习UE4的经验,也为了巩固知识,便于复习. 接下来我会以模块化的方式,根据步骤来分享学习制作的经验,如 ...

  5. 如何利用ChatPDF快速阅读英文论文,帮你写文章

    如何利用ChatPDF快速阅读英文论文,帮你写文章 英语渣狂喜-确实惊艳到我了! 使用平台:https://www.chatpdf.com/ 1.上传PDF 访问官网:https://www.chat ...

  6. 利用Excel快速创建多引脚元器件、如何让引脚倒序排列、如何隐藏管脚名称、如何更新原理图中的元件符号、如何查看元件的所有页面,以及切换页面

    Allegro如何生成光绘文件 导出gerber文件步骤 allegro更改字体和大小(丝印,位号等 利用Excel快速创建多引脚元器件 如何让引脚倒序排列 如何隐藏管脚名称 如何更新原理图中的元件符 ...

  7. 利用爬虫快速获取企业招聘信息

    基于JSoup的HTML解析(以58同城为例) House.java package com.newer.spider;public class House {String room;String d ...

  8. CentOS 5.5 编译安装apache+php+mysql,利用CMS快速建立论坛

    这个是转来的,细节没有验证,请网友自己斟酌.......... CentOS 5.5 编译安装apache+php+mysql,利用CMS快速建立论坛 1.安装Apache [root@bogon t ...

  9. mysql回滚用法_Mysql误操作后利用binlog2sql快速回滚的方法详解

    前言 在日常工作或者学习中,操作数据库时候难免会因为"大意"而误操作,需要快速恢复的话通过备份来恢复是不太可能的,下面这篇文章主要给大家介绍关于Mysql误操作后利用binlog2 ...

最新文章

  1. R语言数据类型:Logical、Numeric、Integer、Complex、Character、Vectors、Lists、Matrices、Arrays、Factors、DataFrames
  2. Docker镜像相关命令
  3. 阿里云腾讯云服务器配置流程(lnmp或tomcat)
  4. 【征稿倒计时—山东科技大学主办】 2021智能装备与特种机器人国际会议(ICIESR2021)...
  5. Python--第2次平时作业
  6. 【文章】你和自己聊过吗?你很重要
  7. 策略模式实现支持多种类数据库的DBHelp
  8. Bootstrap插件之 下拉菜单 源码分析~~
  9. 1. Browser 对象 - Window 对象
  10. 解决vagrant up出现:An error occurred while downloading the remote file. The errormessage
  11. 本科计算机er发篇论文,其实没有那么难
  12. 什么是应届生?要不要签三方?看看就知道了
  13. 线程的先进先出,后进先出,以及优先级队列
  14. 如何制作自己的网站?
  15. C语言求矩阵的逆(高斯法)
  16. 计算机中可以由用户设置的文件属性,计算机考试模拟试题
  17. php 发送带附件邮件
  18. 绝对经典的原理定理理论原则效应法则
  19. Lodop横向打印,正向显示问题
  20. Linux之音视频入门

热门文章

  1. STM32F103ZE uIP DM9051 SPI以太网移植指南
  2. 在python是什么意思_Python a=b是什么意思?
  3. 感抗、容抗、阻抗 计算
  4. 鸿蒙系统主页面斜纹,《中国美术欣赏》[精选].doc
  5. 电容降压整流电源电路
  6. java中怎么引用圆周率_Java简单计算圆周率完整示例
  7. matlab中ode指令,matlab中ode5函数编写.doc
  8. 算法分析之大O、大Ω、大Θ和小o表示法
  9. ctfshow 做题 萌新 模块(1)
  10. ctfshow_密码3