做题之前先复习下【STL中的Tuple容器】

我们知道,在Python中,大家都知道tuple这个概念,是一个只读的元素容器,容器内的元素数据类型可以不同,而在CPP中大部分的容器只能储存相同数据类型的数据,而std::pair函数是为数不多的可以将两个不同类型的值放到一起。我们今天说的tuple是std::pair的推广,表示固定大小的异类值的汇集。
std::tuple是C++11标准开始提出的,其有很多用途,比如一个函数如果拥有多个不同类型的返回值,就可以直接返回一个tuple.不用再像以前一样,定义一个class或者struct保存结果进行返回那么麻烦了!
其使用的重要函数有:

  • std::make_tuple 创建一个tuple对象

  • std::tie 创建左值引用的tuple,或将tuple解包为独立对象

  • std::get(std::tuple) 元组式访问指定的元素

  • 结构化绑定(重要,效率最高),避免使用std::tie函数

使用Demo示例:

#include <tuple>
#include <iostream>
#include <string>
#include <stdexcept> std::tuple<double, char, std::string> get_student(int id)
{
if (id == ) return std::make_tuple(3.8, 'A', "Lisa Simpson");
if (id == ) return std::make_tuple(2.9, 'C', "Milhouse Van Houten");
if (id == ) return std::make_tuple(1.7, 'D', "Ralph Wiggum");
throw std::invalid_argument("id");
} int main()
{
auto student0 = get_student();
std::cout << "ID: 0, "
<< "GPA: " << std::get<>(student0) << ", "
<< "grade: " << std::get<>(student0) << ", "
<< "name: " << std::get<>(student0) << '\n'; double gpa1;
char grade1;
std::string name1;
std::tie(gpa1, grade1, name1) = get_student();
std::cout << "ID: 1, "
<< "GPA: " << gpa1 << ", "
<< "grade: " << grade1 << ", "
<< "name: " << name1 << '\n'; // C++17 结构化绑定, 不用定义变量,也不用使用tie函数
auto [ gpa2, grade2, name2 ] = get_student();
std::cout << "ID: 2, "
<< "GPA: " << gpa2 << ", "
<< "grade: " << grade2 << ", "
<< "name: " << name2 << '\n';
}

好了,复习完知识,下面正式解题。。。。

编写一个程序,通过已填充的空格来解决数独问题。

一个数独的解法需遵循如下规则:

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 '.' 表示。

Note:
给定的数独序列只包含数字 1-9 和字符 '.' 。
你可以假设给定的数独只有唯一解。
给定数独永远是 9x9 形式的

【解题思路】

官方的解答已经很好很清晰了,希望大家可以去看一下,主要思想为约束编程和回溯!
约束编程意思是当我们向未知位置填数时,就需要排除其所在行或者所在列以及所在子方格对该数字的使用!在程序中我们分别使用col_, row_, block_三个二维数组记录数字是否被使用,即如果数字使用了,所对应的位置为true。

回溯法意思是我们需要对每个未知位置进行递归求解,使用数字1-9依次进行尝试,如果在col_, row_, block_用到了该数字,则直接continue,否则我们从这个数字开始递归求解,如果不满足条件,则回溯,并初始化相应的状态,换另外一个数字进行递归!

class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
for (auto i = ; i < ; ++i) {
for (auto j = ; j < ; ++j) {
auto ch = board[i][j];
if (ch == '.') {
spaces_.emplace_back(i, j); // space_用于储存未知位置的行和列
} else {
const auto b = * (i / ) + (j / );
ch -= '';
// 如果数独中有对应数字,则其所在的行,列,block均标记为true,即不可以再使用
row_[i][ch] = true;
col_[j][ch] = true;
block_[b][ch] = true;
}
}
}
solve(board, );
} bool solve(vector<vector<char>>& board, const int pos) {
if (pos < spaces_.size()) {
//int x_, y_;
//std::tie (x_, y_) = spaces_.at(pos);
const auto& [x_, y_] = spaces_.at(pos);
const auto b = * (x_ / ) + (y_ / );
for (auto i = ; i < ; ++i) {
if (row_[x_][i] || col_[y_][i] || block_[b][i])
continue; // 如果数字使用过了,直接返回,否则使用该数字进行递归
board[x_][y_] = '' + i;
row_[x_][i] = true;
col_[y_][i] = true;
block_[b][i] = true; // 使用i,并进行标记 if (solve(board, pos + )) { // 递归到下一个未知位置
return true;
} board[x_][y_] = '.'; // 如果不满足条件,则回溯,恢复为原来的状态
row_[x_][i] = false;
col_[y_][i] = false;
block_[b][i] = false;
}
return false;
}
return true;
} private:
bool row_[][] = {};
bool col_[][] = {};
bool block_[][] = {};
vector<tuple<int, int>> spaces_ = {};
};

【LeetCode】解数独的更多相关文章

  1. 20191030-带返回值的回溯算法Leetcode解数独

    题目描述 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一个以粗实线分隔 ...

  2. Leetcode之回溯法专题-37. 解数独(Sudoku Solver)

    Leetcode之回溯法专题-37. 解数独(Sudoku Solver) 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次.数字 1 ...

  3. Java实现 LeetCode 37 解数独

    37. 解数独 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一个以粗实 ...

  4. leetcode 36 有效的数独 哈希表 unordered_set unordersd_map 保存状态 leetcode 37 解数独

    leetcode 36 感觉就是遍历. 保存好状态,就是各行各列还有各分区divide的情况 用数组做. 空间小时间大 class Solution { public: bool isValidSud ...

  5. [leetcode]37. Sudoku Solver 解数独

    Write a program to solve a Sudoku puzzle by filling the empty cells. A sudoku solution must satisfy  ...

  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] 37. 解数独(Java)(dfs,递归,回溯)

    37. 解数独 1A 这个题其实15分钟左右就敲出来并且对了...但是由于我输错了一个数..导致我白白debug一个多小时.. 没啥难度,练递归-dfs的好题 class Solution { pri ...

  8. 【原创】一个基于简单剪枝的DFS解数独程序

    问题来源:leetCode Sudoku Solver Write a program to solve aSudoku puzzle by filling the empty cells. Empt ...

  9. LeetCode37 使用回溯算法实现解数独,详解剪枝优化

    本文始发于个人公众号:TechFlow,原创不易,求个关注 数独是一个老少咸宜的益智游戏,一直有很多拥趸.但是有没有想过,数独游戏是怎么创造出来的呢?当然我们可以每一关都人工设置,但是显然这工作量非常 ...

  10. 用C++实现的解数独(Sudoku)程序

    我是一个C++初学者,控制台实现了一个解数独的小程序. 代码如下: //"数独游戏"V1.0 //李国良于2016年11月11日编写完成 #include <iostream ...

随机推荐

  1. 运算符 Operator 及优先级

    算数运算符 + - * / ** % /表示自然除,结果是浮点数.//为整除.python2.x版本/和//都是整除. 位运算符 & | ~ ^ << >> <& ...

  2. vue通过路由传值及在页面刷新后如何保存值

    1.普通的路由跳转 方式一:通过routerLinkTo方式,转为a标签的跳转,to里面相当于a标签的href路径 如下: 方式二:通过this.$router.push方式: 如下: 2.带参数的路 ...

  3. 在Linux上安装Oracle服务的操作步骤

    如题,将我在云服务器上安装Oracle服务的惨痛经历分享出来,期间查找的资料踩过的坑无数,希望对大家能有帮助 闲话少叙,直接开始 首先,由于服务器比较差,需要先设置swap 查看是否设置swap虚拟内 ...

  4. 渗透测试神器Burp Suite v1.7.11发布(含下载)

    BurpSuite是一款信息安全从业人员必备的集成型的渗透测试工具,它采用自动测试和半自动测试的方式,包含了Proxy,Spider,Scanner,Intruder,Repeater,Sequenc ...

  5. JdbcTemplate常用方法

    JdbcTemplate简介 JdbcTemplate是Spring JDBC的核心类,借助该类提供的方法可以很方便的实现数据的增删改查. Spring对数据库的操作在jdbc上面做了深层次的封装,使 ...

  6. springboot2.1mysql驱动类弃用

    Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdb ...

  7. node - multer 加图片后缀

    var multer = require('multer') var storage = multer.diskStorage({   destination: function (req, file ...

  8. ​IntelliJ IDEA使用技巧—使用EasyCode插件一键生成代码04期

    在现如今的软件开发过程中,软件开发人员将很多的精力放在重复的编码中.特别是流行的MVC架构模式下,项目各个层次的功能更加独立,这也间接的造成了代码的相似度更高.因此需要寻找一种可以减少软件开发人员重复 ...

  9. 018、MySQL取满足日期在两个日期之间的所有数据

    #查询 SELECT GZJK_CREATEDATE FROM abc_table WHERE ( ( GZJK_CREATEDATE >= UNIX_TIMESTAMP( '2019-08-0 ...

  10. 六、Vue-Router:基础路由处理、路由提取成单独文件、路由嵌套、路由传参数、路由高亮、html5的history使用

    一.vue-router的安装 官网文档 [官网]:https://cn.vuejs.org/v2/guide/routing.html [router文档]:https://router.vuejs ...