利用计算机程序快速得到9*9大小数独的解法
对于 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大小数独的解法相关推荐
- 利用 画图 快速给图片添加文字
利用 画图 快速给图片添加文字 有时候我们需要给某些图片上添加文字,大多数人可能第一时间会想到PS,其实如果我们只是添加文字的话,Windows下的 画图 工具也是非常不错的选择. 我们选择要编辑的图 ...
- 如何利用CCleaner快速查找重复文件?
一般的电脑随着时间的推移磁盘里面会有多份的重复文件,这些重复项会占用硬盘驱动器上面的空间,并且很难追踪到文件的位置以及更改的文件.但是CCleaner却轻松的解决了这个问题,那么如何利用CCleane ...
- 利用PS快速抠图的5个超实用技巧
利用PS快速抠图的5个超实用技巧 抠图是图像处理中最常做的操作之一,也是photoshop中最为常用的技术之一.抠图其实并不难,只要你有足够的耐心和细心,只须掌握PS中一些基础知识就能完美的抠出图片. ...
- Unreal Engin_画廊制作笔记_001<设计草图,利用BSP快速搭建简单场景>
001设计草图,利用BSP快速搭建简单场景 本笔记开始记录所学的知识点以及细节操作等,分享下自己学习UE4的经验,也为了巩固知识,便于复习. 接下来我会以模块化的方式,根据步骤来分享学习制作的经验,如 ...
- 如何利用ChatPDF快速阅读英文论文,帮你写文章
如何利用ChatPDF快速阅读英文论文,帮你写文章 英语渣狂喜-确实惊艳到我了! 使用平台:https://www.chatpdf.com/ 1.上传PDF 访问官网:https://www.chat ...
- 利用Excel快速创建多引脚元器件、如何让引脚倒序排列、如何隐藏管脚名称、如何更新原理图中的元件符号、如何查看元件的所有页面,以及切换页面
Allegro如何生成光绘文件 导出gerber文件步骤 allegro更改字体和大小(丝印,位号等 利用Excel快速创建多引脚元器件 如何让引脚倒序排列 如何隐藏管脚名称 如何更新原理图中的元件符 ...
- 利用爬虫快速获取企业招聘信息
基于JSoup的HTML解析(以58同城为例) House.java package com.newer.spider;public class House {String room;String d ...
- CentOS 5.5 编译安装apache+php+mysql,利用CMS快速建立论坛
这个是转来的,细节没有验证,请网友自己斟酌.......... CentOS 5.5 编译安装apache+php+mysql,利用CMS快速建立论坛 1.安装Apache [root@bogon t ...
- mysql回滚用法_Mysql误操作后利用binlog2sql快速回滚的方法详解
前言 在日常工作或者学习中,操作数据库时候难免会因为"大意"而误操作,需要快速恢复的话通过备份来恢复是不太可能的,下面这篇文章主要给大家介绍关于Mysql误操作后利用binlog2 ...
最新文章
- R语言数据类型:Logical、Numeric、Integer、Complex、Character、Vectors、Lists、Matrices、Arrays、Factors、DataFrames
- Docker镜像相关命令
- 阿里云腾讯云服务器配置流程(lnmp或tomcat)
- 【征稿倒计时—山东科技大学主办】 2021智能装备与特种机器人国际会议(ICIESR2021)...
- Python--第2次平时作业
- 【文章】你和自己聊过吗?你很重要
- 策略模式实现支持多种类数据库的DBHelp
- Bootstrap插件之 下拉菜单 源码分析~~
- 1. Browser 对象 - Window 对象
- 解决vagrant up出现:An error occurred while downloading the remote file. The errormessage
- 本科计算机er发篇论文,其实没有那么难
- 什么是应届生?要不要签三方?看看就知道了
- 线程的先进先出,后进先出,以及优先级队列
- 如何制作自己的网站?
- C语言求矩阵的逆(高斯法)
- 计算机中可以由用户设置的文件属性,计算机考试模拟试题
- php 发送带附件邮件
- 绝对经典的原理定理理论原则效应法则
- Lodop横向打印,正向显示问题
- Linux之音视频入门