【回溯 状态压缩 深度优先】37. 解数独

本文涉及知识点

回溯 状态压缩 深度优先

LeetCode37. 解数独

编写一个程序,通过填充空格来解决数独问题。
数独的解法需 遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

示例 1:
输入:board = [[“5”,“3”,“.”,“.”,“7”,“.”,“.”,“.”,“.”],[“6”,“.”,“.”,“1”,“9”,“5”,“.”,“.”,“.”],[“.”,“9”,“8”,“.”,“.”,“.”,“.”,“6”,“.”],[“8”,“.”,“.”,“.”,“6”,“.”,“.”,“.”,“3”],[“4”,“.”,“.”,“8”,“.”,“3”,“.”,“.”,“1”],[“7”,“.”,“.”,“.”,“2”,“.”,“.”,“.”,“6”],[“.”,“6”,“.”,“.”,“.”,“.”,“2”,“8”,“.”],[“.”,“.”,“.”,“4”,“1”,“9”,“.”,“.”,“5”],[“.”,“.”,“.”,“.”,“8”,“.”,“.”,“7”,“9”]]
在这里插入图片描述

输出:[[“5”,“3”,“4”,“6”,“7”,“8”,“9”,“1”,“2”],[“6”,“7”,“2”,“1”,“9”,“5”,“3”,“4”,“8”],[“1”,“9”,“8”,“3”,“4”,“2”,“5”,“6”,“7”],[“8”,“5”,“9”,“7”,“6”,“1”,“4”,“2”,“3”],[“4”,“2”,“6”,“8”,“5”,“3”,“7”,“9”,“1”],[“7”,“1”,“3”,“9”,“2”,“4”,“8”,“5”,“6”],[“9”,“6”,“1”,“5”,“3”,“7”,“2”,“8”,“4”],[“2”,“8”,“7”,“4”,“1”,“9”,“6”,“3”,“5”],[“3”,“4”,“5”,“2”,“8”,“6”,“1”,“7”,“9”]]
解释:输入的数独如上图所示,唯一有效的解决方案如下所示:
提示:
在这里插入图片描述

board.length == 9
board[i].length == 9
board[i][j] 是一位数字或者 ‘.’
题目数据 保证 输入数独仅有一个解

回溯

vRow[i] 记录第i行可以选择那些数,vCol[i]和vCell类型。
vRow[i] & ( 1 << j) 表示第i行,可以选择数组j。
直接将选择结果修改到board上。
vector<tuple<int,int,int>> vSel。 i1,记录可以选择的数量,i2记录行号,i3记录列号。注意:只需要记录能修改的数组。 初始化结束后,对vSel排序。理论上:只有一种选择的先选快点。实际上几乎无影响。
用深度优先实现。Fill 函数填写某行某列,UnFill 恢复某行某列原装。
时间复杂度:不好计算。

代码

核心代码

class CBitCounts
{
public:CBitCounts(int iMaskCount){for (int i = 0; i < iMaskCount; i++){m_vCnt.emplace_back(bitcount(i));}}template<class T>static int bitcount(T x) {int countx = 0;while (x) {countx++;x &= (x - 1);}return countx;}vector<int> m_vCnt;
};class Solution {
public:void solveSudoku(vector<vector<char>>& board) {m_board = board;int mask = 0;for (int i = 1; i <= 9; i++) {mask |= (1 << i);}for (int i = 0; i < 9; i++) {m_rows[i] = m_cols[i] = m_cells[i] = mask;}for (int r = 0; r < 9; r++) {for (int c = 0; c < 9; c++) {if ('.' == board[r][c]) { continue; }Fill(r, c, board[r][c] - '0');}}vector<tuple<int, int, int,int>> vSel;for (int r = 0; r < 9; r++) {for (int c = 0; c < 9; c++) {if ('.' != board[r][c]) { continue; }int iCell = r / 3 * 3 + c / 3;int mask = m_rows[r] & m_cols[c] & m_cells[iCell];vSel.emplace_back(CBitCounts::bitcount(mask), r, c,iCell);}}sort(vSel.begin(), vSel.end());DFS(vSel, 0);board = m_board;}bool DFS(const vector<tuple<int, int, int,int>> vSel, int leve) {if (vSel.size() == leve) { return true; }const auto& [tmp, r, c, iCell] = vSel[leve];int mask = m_rows[r] & m_cols[c] & m_cells[iCell];for (int i = 1; i <= 9; i++) {if (mask & (1 << i)) {Fill(r, c, i);if (DFS(vSel, leve + 1)) { return true; }UnFill(r, c, i);}}return false;}void Fill (int r, int c, int val) {m_board[r][c] = val + '0';m_rows[r] &= ~(1 << val);m_cols[c] &= ~(1 << val);int iCell = r / 3 * 3 + c / 3;m_cells[iCell] &= ~(1 << val);};void UnFill(int r, int c, int val) {m_board[r][c] = '.';m_rows[r] |= (1 << val);m_cols[c] |= (1 << val);int iCell = r / 3 * 3 + c / 3;m_cells[iCell] |= (1 << val);};vector<vector<char>> m_board;int m_rows[9], m_cols[9], m_cells[9];
};

测试用例

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){assert(v1[i] == v2[i]);}
}template<class T>
void Assert(const T& t1, const T& t2)
{assert(t1 == t2);
}int main()
{vector<vector<char>> board;{Solution slu;board ={ {'5', '3', '.', '.', '7', '.', '.', '.', '.'}, { '6','.','.','1','9','5','.','.','.' }, { '.','9','8','.','.','.','.','6','.' }, { '8','.','.','.','6','.','.','.','3' }, { '4','.','.','8','.','3','.','.','1' }, { '7','.','.','.','2','.','.','.','6' }, { '.','6','.','.','.','.','2','8','.' }, { '.','.','.','4','1','9','.','.','5' }, { '.','.','.','.','8','.','.','7','9' }};slu.solveSudoku(board);vector<vector<char>> board1={ {'5', '3', '4', '6', '7', '8', '9', '1', '2'}, { '6','7','2','1','9','5','3','4','8' }, { '1','9','8','3','4','2','5','6','7' }, { '8','5','9','7','6','1','4','2','3' }, { '4','2','6','8','5','3','7','9','1' }, { '7','1','3','9','2','4','8','5','6' }, { '9','6','1','5','3','7','2','8','4' }, { '2','8','7','4','1','9','6','3','5' }, { '3','4','5','2','8','6','1','7','9' }};Assert(board1, board);}	
}

2023年5月代码

记录已经选择的数,这样初始化简单。用二维数组记录3 × \times × 3 网格的情况,减少计算网格号。

class Solution {
public:void solveSudoku(vector<vector<char>>& board) {memset(m_aRows, 0, sizeof(m_aRows));memset(m_aCols, 0, sizeof(m_aCols));memset(m_aBlock, 0, sizeof(m_aBlock));for (int r = 0; r < 9; r++){for (int c = 0; c < 9; c++){const char& ch = board[r][c];if ('.' == ch){m_vNeedDoRowCols.emplace_back(r, c);continue;}Add(r, c, ch - '1');}}dfs(board, 0);}bool dfs(vector<vector<char>>& board,int iLeve){if (m_vNeedDoRowCols.size() == iLeve){return true;}const int r = m_vNeedDoRowCols[iLeve].first;const int c = m_vNeedDoRowCols[iLeve].second;int iMask = m_aRows[r] | m_aCols[c] | m_aBlock[r/3][c/3];for (int i = 0; i < 9; i++){if (iMask & (1 << i)){continue;}Add(r, c, i);board[r][c] = '1' + i;if (dfs(board, iLeve + 1)){return true;}board[r][c] = '.';Erase(r, c, i);}return false;}void Add(int r, int c, int iNum){const int iMask = 1 << iNum;m_aRows[r] |= iMask;m_aCols[c] |= iMask;m_aBlock[r / 3][c / 3] |= iMask;}void Erase(int r, int c, int iNum){const int iMask = 1 << iNum;m_aRows[r] -= iMask;m_aCols[c] -= iMask;m_aBlock[r / 3][c / 3] -= iMask;}int m_aRows[9],m_aCols[9];int m_aBlock[3][3];vector<std::pair<int, int>> m_vNeedDoRowCols;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/9951.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetCode刷题记录4-面试经典150题-2

文章目录 不要摆&#xff0c;没事干就刷题&#xff0c;只有好处&#xff0c;没有坏处&#xff0c;实在不行&#xff0c;看看竞赛题面试经典 150 题 - 2210. 课程表 II 不要摆&#xff0c;没事干就刷题&#xff0c;只有好处&#xff0c;没有坏处&#xff0c;实在不行&#xff0c…

[C++核心编程-06]----C++类和对象之对象模型和this指针

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

Microsoft 365 for Mac v16.84 office365全套办公软件

Microsoft 365 for Mac是一款功能丰富的办公软件套件&#xff0c;为Mac用户提供了丰富的功能和工具&#xff0c;提高了工作效率和协作能力。Microsoft 365 for Mac是一款专为Mac用户设计的订阅式办公软件套件&#xff0c;旨在提高生产力和效率。 Microsoft 365 for Mac v16.84正…

数据赋能(83)——数据要素:数据要素管理与数据管理

数据要素管理则更关注数据作为生产性资源在创造经济价值中的作用&#xff1b;数据管理更侧重于数据在整个生命周期中的控制、保护和价值提升。 数据要素管理是对数据作为关键生产要素进行系统性管理的过程。它聚焦于数据在经济和社会活动中的价值创造和贡献&#xff0c;将数据…

ubantu安装docker以及docker-compose

ubantu安装docker以及docker-compose 安装docker1、从官方存储库中安装Docker2、启动Docker服务3、验证 安装docker compose使用docker部署服务1、需要再opt文件夹下创建以下文件夹&#xff0c;/opt文件夹目录说明2、可将已备份对应文件夹拷至对应文件夹下3、在/opt/compose目录…

python集合

集合是一个无序的不重复元素序列&#xff0c;集合中的元素必须是不可变类型 集合的创建与删除 用{}直接创建 用集合推导式创建 用ser&#xff08;&#xff09;函数将列表&#xff0c;元组&#xff0c;range对象转换成集合 numset1{1,2,3,4,5}numset2{x**2 for x in range(…

【代码】Mysql 查询近一个月各类型设备新增数量

错误示例 SELECT COUNT(*) AS count, p.type, d.active_date FROM device d LEFT JOIN product p ON d.product_id p.pid WHERE MONTH (active_date) MONTH (CURRENT_DATE - INTERVAL 1 MONTH) AND YEAR (active_date) YEAR (CURRENT_DATE - INTERVAL 1 MONTH) group by p.…

mysql高可用集群MGR组复制的介绍、部署及配置说明

前言 MGR全称MySQL Group Replication(Mysql组复制),是MySQL官方于2016年12月推出的一个全新的高可用与高扩展的解决方案。MGR提供了高可用、高扩展、高可靠的MySQL集群服务。 高一致性:基于分布式paxos协议实现组复制,保证数据一致性; 高容错性:自动检测机制,只要不…

霍金《时间简史 A Brief History of Time》书后索引(A--D)

图源&#xff1a;Wikipedia INDEX A Abacus Absolute position Absolute time Absolute zero Acceleration Age of the universe Air resistance Albrecht, Andreas Alpha Centauri Alpher, Ralph Anthropic principle Antigravity Antiparticles Aristotle Arrows of time …

基于Vant UI的微信小程序开发(随时更新的写手)

基于Vant UI的微信小程序开发✨ &#xff08;一&#xff09;悬浮浮动1、效果图&#xff1a;只要无脑引用样式就可以了2、页面代码3、js代码4、样式代码 &#xff08;二&#xff09;底部跳转1、效果图&#xff1a;点击我要发布跳转到发布的页面2、js代码3、页面代码4、app.json代…

vue项目设置主题色

在vue开发过程中&#xff0c;很多页面为了保持主题颜色统一&#xff0c;且方便后期管理&#xff0c;通常会设有主题色&#xff0c;通过主题色可以使得页面上的按钮单选框等控件保持颜色统一。 接下来介绍其中一种方法&#xff1a; 1.先建立一个js文件用于存放主题色&#xff…

我觉得POC应该贴近实际

今天我看到一位老师给我一份测试数据。 这是三个国产数据库。算是分布式的。其中有两个和我比较熟悉&#xff0c;但是这个数据看上去并不好。看上去第一个黄色的数据库数据是这里最好的了。但是即使如此&#xff0c;我相信大部分做数据库的人都知道。MySQL和PostgreSQL平时拿出…

Spark Streaming笔记总结(保姆级)

万字长文警告&#xff01;&#xff01;&#xff01; 目录 一、离线计算与流式计算 1.1 离线计算 1.1.1 离线计算的特点 1.1.2 离线计算的应用场景 1.1.3 离线计算代表技术 1.2 流式计算 1.2.1 流式计算的特点 1.2.2 流式计算的应用场景 1.2.3 流式计算的代表技术 二…

最小生成树刷题笔记

算法基础&#xff1a; 首先是prim算法三部曲&#xff1a; &#xff08;1&#xff09;找到距离最小生成树最近的节点。 &#xff08;2&#xff09;将距离最小生成树最近的节点加入到最小生成树中。 &#xff08;3&#xff09;更新非最小生成树节点到最小生成树的距离。 实现…

HTML批量文件上传3—Servlet批量文件处理FileUpLoad

作者:私语茶馆 1.开源的文件上传组件介绍 本文使用的是Apache Commons下面的一个子项目FileUpload,另外一个常见组件是SmartUpload。FileUpload遵循RFC 1897,即“Form-based File Upload in HTML”,对于请求需要满足:HTTP协议,Post请求,content Type=“multipart/form-d…

Kafka 面试题(五)

1. kafka的消费者是pull(拉)还是push(推)模式&#xff0c;这种模式有什么好处&#xff1f; Kafka的消费者是pull&#xff08;拉&#xff09;模式。在这种模式下&#xff0c;消费者主动从Kafka的broker中拉取数据来进行消费。 这种pull模式的好处主要体现在以下几个方面&#…

人工智能是什么

人工智能是一个广泛的领域&#xff0c;其中包括了机器学习和深度学习。 - 机器学习&#xff1a; 是人工智能的一个子领域&#xff0c;它关注的是让计算机系统通过学习数据&#xff0c;从中获取知识并做出预测或决策&#xff0c;而无需明确地编写特定的规则。机器学习的方法包括…

kernel32.dll丢失要如何解决?电脑kernel32.dll文件下载方法

kernel32.dll丢失要怎么解决才好&#xff1f;其实针对这个问题还是有很多种的解决方法的&#xff0c;只要你明白了kernel32.dll的作用&#xff0c;了解kernel32.dll&#xff0c;那么就可以有很多种方法去解决&#xff0c;下面一起来看看吧。 一.了解kernel32.dll文件 kernel32…

6个超TM好用的神仙App推荐!

1. AI文本视频生成工具——Jurilu Jurilu 是一款功能强大的 AI 文本视频生成器&#xff0c;允许用户快速将文本内容转换成极具吸引力的视频。它的使用非常简单&#xff1a;只需要输入文字&#xff0c;选择想要的样式和模板&#xff0c;Jurilu 就会自动将文字转换成生动的视频。…

Vue项目npm install certificate has expired报错解决方法

1.Vue项目 npm install 安装依赖突然报错&#xff1a; npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to https://registry.npm.taobao.org/zrender/download/zrender-4.3.0.tgz failed, reason: certificate has expired npm ERR! A com…