[LeetCode] Sudoku Solver 解数独,递归,回溯
Write a program to solve a Sudoku puzzle by filling the empty cells.
Empty cells are indicated by the character '.'.
You may assume that there will be only one unique solution.
![]()
A sudoku puzzle...
![]()
...and its solution numbers marked in red.
- 创建一个辅助函数,help(vector<vector<char> > & board,int i,int ii,int j,int jj),其中i为第几行,j 第几列,ii 小框中的第几行,jj 小框中第几列。
- help 函数4层for 循环遍历整个9*9 矩阵,说是4层,跟两次for 是一样的,i 和j 的步长是3,for(;i<9;i+=3),因为这4个变量的初始化在函数传入的时候,所以在其循环结束时候尾部赋0,其中一个不好的地方。
- 4层循环内部,首先判断当前格board[i+ii][j+jj]是否为数字,不然继续循环。
- 创建标记finish = false,标记接下来的填入(当前格为空)能否完成整个矩阵,用于控制跳出填写,和如果填写失败修复当前格为'.' 回溯。
- 遍历1-9 尝试填写,需要用到bool canIn=true,判断行,列,框中的情况,如果通过判断则修改当框为遍历的数字,递归下一格,输入当前格的i ii j jj,便可以,这是第二个不好的地方,判断没有写为外部函数,另外函数的参数设置导致了很多细节问题。
- 下层返回的值赋予 finish ,如果为false ,表示当前填写不行,继续遍历,如果为true,跳出填写的遍历。
- 结束遍历后判断是否已经填写整个矩阵,如果finish 为false,表示失败了,则当前格,然后返回false,成功先别返回。
- 外部4层循环结束返回true。
所以在外层循环后返回true,是假如例子上的情况,最后一个格不为空,那么按上面逻辑是不会进入内部的,而如果能够全部遍历完整个矩阵,那么表示没有在内部返回,等价于成功填写了。
之所以使用 ii jj,是为了可以方便处理3*3框,在能否填写的时候,需要注意跳过自身与自身判断,先判断行列,然后框的时候变可以跳过当前框所在的行列了。
#include <vector>
#include <iostream>
#include <iterator>
using namespace std; class Solution {
public:
void solveSudoku(vector<vector<char> > &board) {
help(board,,,,);
}
bool help(vector<vector<char> > & board,int i,int ii,int j,int jj){
for(;i<;i+=){
for(;ii<;ii++){
for(;j<;j+=){
for(;jj<;jj++){
if(board[i+ii][j+jj]!='.') continue;
bool finish = false;
for(char c='';c<=''&&!finish;c++){
bool canIn= true;
for(int k=;k<&&canIn;k++){
if(k!=i+ii&&board[k][j+jj]==c) canIn = false;
if(k!=j+jj&&board[i+ii][k]==c) canIn = false;
}
for(int ti=;ti<&&canIn;ti++){
if(ti == ii) continue;
for(int tj=;tj<&&canIn;tj++){
if(tj==jj) continue;
if(board[ti+i][tj+j]==c) canIn = false;
}
}
if(canIn==false) continue;
board[i+ii][j+jj] = c;
finish = help(board,i,ii,j,jj);
}
if(!finish){ board[i+ii][j+jj] = '.'; return false; }
}
jj = ;
}
j=;
}
ii=;
}
return true;
}
}; int main()
{
vector<char> line;
vector<vector<char> > board;
line = {'','','.','.','','.','.','.','.'};
board.push_back(line);
line.clear();
line = {'','.','.','','','','.','.','.'};
board.push_back(line);
line.clear();
line = {'.','','','.','.','.','.','','.'};
board.push_back(line);
line.clear();
line = {'','.','.','.','','.','.','.',''};
board.push_back(line);
line.clear();
line = {'','.','.','','.','','.','.',''};
board.push_back(line);
line.clear();
line = {'','.','.','.','','.','.','.',''};
board.push_back(line);
line.clear();
line = {'.','','.','.','.','.','','','.'};
board.push_back(line);
line.clear();
line = {'.','.','.','','','','.','.',''};
board.push_back(line);
line.clear();
line = {'.','.','.','.','','.','.','',''};
board.push_back(line);
Solution sol;
sol.solveSudoku(board);
for(int i=;i<board.size();i++){
copy(board[i].begin(),board[i].end(),ostream_iterator<char>(cout," "));
cout<<endl;
}
return ;
}
[LeetCode] Sudoku Solver 解数独,递归,回溯的更多相关文章
- [leetcode]37. Sudoku Solver 解数独
Write a program to solve a Sudoku puzzle by filling the empty cells. A sudoku solution must satisfy ...
- [LeetCode] Sudoku Solver 求解数独
Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...
- 037 Sudoku Solver 解数独
写一个程序通过填充空格来解决数独.空格用 '.' 表示. 详见:https://leetcode.com/problems/sudoku-solver/description/ class Solut ...
- LeetCode:Valid Sudoku,Sudoku Solver(数独游戏)
Valid Sudoku Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku bo ...
- Sudoku Solver, 求数独
问题描述:填充数独表中空元素.空元素为'.' 算法分析:没填充一个数,都要看这个数所在的行,列,小矩阵是否合法.然后还要看整个数独表是否正确,而判断整个数独表只能通过递归,因为前一个结果的判断要依赖后 ...
- [LeetCode] 37. Sudoku Solver 求解数独
Write a program to solve a Sudoku puzzle by filling the empty cells. A sudoku solution must satisfy ...
- LeetCode OJ:Sudoku Solver(数独游戏)
Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...
- Leetcode: Sudoku Solver
July 19, 2015 Problem statement: Write a program to solve a Sudoku puzzle by filling the empty cells ...
- [LeetCode] Sudoku Solver(迭代)
Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...
随机推荐
- linux主机状态检测方式
之前写过一个简单的脚本检测当前网段中主机状态的脚本,内容如下: #! /bin/bash #ping check host status trap "exit" 2 sping() ...
- centos7中使用LVM管理磁盘和挂载磁盘
centos7使用LVM管理一块新的磁盘 注意!文中凡是带#的都是命令标志. 一些重要概念: LV(Logical Volume)- 逻辑卷, VG(Volumne Group)- 卷组, PV(Ph ...
- Spark架构与作业执行流程简介(scala版)
在讲spark之前,不得不详细介绍一下RDD(Resilient Distributed Dataset),打开RDD的源码,一开始的介绍如此: 字面意思就是弹性分布式数据集,是spark中最基本的数 ...
- VirtualBox下vim无法正常使用问题解决
由原来的使用VMware转到使用Virtual Box,发现其vim编辑器不是特别好用,需要进行一下更改设置: 1.使用命令删除vim,sudo apt-get remove vim-common 2 ...
- 20190102(多线程,守护线程,线程互斥锁,信号量,JoinableQueue)
多线程 多进程: 核心是多道技术,本质上就是切换加保存技术. 当进程IO操作较多,可以提高程序效率. 每个进程都默认有一条主线程. 多线程: 程序的执行线路,相当于一条流水线,其包含了程序的具体执行步 ...
- 动态规划:HDU-2955-0-1背包问题:Robberies
解题心得: 这题涉及概率问题,所以要运用概率的知识进行解答.题目要求不被抓到的概率,但是给出的是被抓到的概率,所要用1减去后得到答案.最好使用double类型,避免精度问题导致WA. 先算出可以抢劫的 ...
- Spring核心技术(十四)——ApplicationContext的额外功能
在前文的介绍中我们知道,org.springframework.beans.factory包提供了一些基本的功能来管理和控制Bean,甚至通过编程的方式来实现.org.springframework. ...
- Go语言之并发编程(一)
轻量级线程(goroutine) 在编写socket网络程序时,需要提前准备一个线程池为每一个socket的收发包分配一个线程.开发人员需要在线程数量和CPU数量间建立一个对应关系,以保证每个任务能及 ...
- “帮你APP”团队冲刺6
1.整个项目预期的任务量 (任务量 = 所有工作的预期时间)和 目前已经花的时间 (所有记录的 ‘已经花费的时间’),还剩余的时间(所有工作的 ‘剩余时间’) : 所有工作的预期时间:88h 目前已经 ...
- SXCPC2018 nucoj2004 国王的怪癖
可持久化trie.考场上我脑补了一个trie树合并也A了 #include <iostream> #include <cstring> #include <cstdio& ...