【Sudoku Solver】cpp
题目:
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.
代码:
class Solution {
public:
void solveSudoku(vector<vector<char> >& board)
{
vector<pair<int, int> > emptyCells;
vector<set<char> > rowSet, colSet, matrixSet;
set<char> row, col, matrix;
for ( size_t i = ; i < ; ++i )
{
row.clear(); col.clear(); matrix.clear();
for ( size_t j = ; j < ; ++j )
{
if (board[i][j]!='.'){
row.insert(board[i][j]);
}
else{
emptyCells.push_back(make_pair(i, j));
}
if (board[j][i]!='.') col.insert(board[j][i]);
int r = j/+(i/)*, c = j%+(i%)*;
if (board[r][c]!='.') matrix.insert(board[r][c]);
}
rowSet.push_back(row); colSet.push_back(col); matrixSet.push_back(matrix);
}
Solution::dfs(board, emptyCells, rowSet, colSet, matrixSet);
}
static bool dfs(
vector<vector<char> >& board,
vector<pair<int, int> >& emptyCell,
vector<set<char> >& rowSet,
vector<set<char> >& colSet,
vector<set<char> >& matrixSet)
{
if ( emptyCell.empty() ) return true;
int i = emptyCell.back().first;
int j = emptyCell.back().second;
for ( char v = ''; v<='' && !emptyCell.empty(); ++v )
{
if (rowSet[i].find(v)==rowSet[i].end() &&
colSet[j].find(v)==colSet[j].end() &&
matrixSet[(i/)*+j/].find(v)==matrixSet[(i/)*+j/].end() )
{
board[i][j]=v;
rowSet[i].insert(v);
colSet[j].insert(v);
matrixSet[(i/)*+j/].insert(v);
emptyCell.pop_back();
if ( Solution::dfs(board, emptyCell, rowSet, colSet, matrixSet) )
{
return true;
}
else
{
emptyCell.push_back(make_pair(i, j));
board[i][j] = '.';
rowSet[i].erase(v);
colSet[j].erase(v);
matrixSet[(i/)*+j/].erase(v);
}
}
}
return false;
}
};
tips:
采用深搜模板。
主要思路走一遍board,得到三个set,一个vector
1. 三个set分别为每行、列、子模块已有的数字
2. 一个vector中存放着'.'的位置
每次处理一个'.',遍历1到9:
1. 如果满足数独的条件,就往下走一层
2. 如果1到9都不满足,则退回到上一层,重新选择上一个位置的元素
这里有一个思维陷阱:
emptyCell.pop_back();
if ( Solution::dfs(board, emptyCell, rowSet, colSet, matrixSet) )
{
return true;
}
else
{
emptyCell.push_back(make_pair(i, j));
board[i][j] = '.';
rowSet[i].erase(v);
colSet[j].erase(v);
matrixSet[(i/)*+j/].erase(v);
}
注意:pop和push操作应该是对应的,之前一直以为可以不用push的操作,原因是忽略了一种情况:如果一个位置从1到9都不满足,那么必然要回溯到上一层;即,某一个位置的元素是可能遍历不止一次1到9的。
=================================
这里set的效率可能有些低,换一个hashmap的效率可能高一些。
class Solution {
public:
void solveSudoku(vector<vector<char> >& board)
{
vector<pair<int, int> > emptyCells;
vector<map<char,bool> > rowSet, colSet, matrixSet;
map<char,bool> row, col, matrix;
for ( size_t i = ; i < ; ++i )
{
for ( char v = '' ; v <= ''; ++v ) { row[v] = col[v] = matrix[v] = false; }
for ( size_t j = ; j < ; ++j )
{
if (board[i][j]!='.'){
row[board[i][j]] = true;
}
else{
emptyCells.push_back(make_pair(i, j));
}
if (board[j][i]!='.') col[board[j][i]]=true;
int r = j/+(i/)*, c = j%+(i%)*;
if (board[r][c]!='.') matrix[board[r][c]]=true;
}
rowSet.push_back(row); colSet.push_back(col); matrixSet.push_back(matrix);
}
Solution::dfs(board, emptyCells, rowSet, colSet, matrixSet);
}
static bool dfs(
vector<vector<char> >& board,
vector<pair<int, int> >& emptyCell,
vector<map<char,bool> >& rowSet,
vector<map<char,bool> >& colSet,
vector<map<char,bool> >& matrixSet)
{
if ( emptyCell.empty() ) return true;
int i = emptyCell.back().first, j = emptyCell.back().second;
for ( char v = ''; v<=''; ++v )
{
if (!rowSet[i][v] && !colSet[j][v] && !matrixSet[(i/)*+j/][v] )
{
board[i][j] = v;
rowSet[i][v] = colSet[j][v] = matrixSet[(i/)*+j/][v] = true;
emptyCell.pop_back();
if ( Solution::dfs(board, emptyCell, rowSet, colSet, matrixSet) ){
return true;
}
else{
emptyCell.push_back(make_pair(i, j));
rowSet[i][v] = colSet[j][v] = matrixSet[(i/)*+j/][v] = false;
}
}
}
return false;
}
};
tips:都换成了hashmap,效率有所提升。
============================================
第二次过这道题,还是sub board那块内容调了几次,AC了。
class Solution {
public:
void solveSudoku(vector<vector<char> >& board)
{
// restore all blank positions
vector<pair<int, int> > blanks;
for ( int i=; i<board.size(); ++i )
{
for ( int j=; j<board[i].size(); ++j )
{
if ( board[i][j]=='.' ) blanks.push_back(make_pair(i, j));
}
}
Solution::dfs(board, blanks);
}
static bool dfs(
vector<vector<char> >& board,
vector<pair<int,int> >& blanks )
{
if ( blanks.empty() ) return true;
const int r = blanks.back().first;
const int c = blanks.back().second;
for ( char v=''; v<=''; ++v )
{
bool valid = true;
// check row & column & subBoard
for ( int i=; i<; ++i )
{
if ( board[r][i]==v || board[i][c]==v || board[i/3+(r/3)*3][i%3+(c/3)*3]==v )
{
valid = false;
break;
}
}
if ( valid )
{
board[r][c] = v;
blanks.pop_back();
if ( Solution::dfs(board, blanks) ) return true;
blanks.push_back(make_pair(r, c));
board[r][c] = '.';
}
}
return false;
}
};
【Sudoku Solver】cpp的更多相关文章
- hdu 4739【位运算】.cpp
题意: 给出n个地雷所在位置,正好能够组成正方形的地雷就可以拿走..为了简化题目,只考虑平行于横轴的正方形.. 问最多可以拿走多少个正方形.. 思路: 先找出可以组成正方形的地雷组合cnt个.. 然后 ...
- Hdu 4734 【数位DP】.cpp
题意: 我们定义十进制数x的权值为f(x) = a(n)*2^(n-1)+a(n-1)*2(n-2)+...a(2)*2+a(1)*1,a(i)表示十进制数x中第i位的数字. 题目给出a,b,求出0~ ...
- 【Permutations II】cpp
题目: Given a collection of numbers that might contain duplicates, return all possible unique permutat ...
- 【Subsets II】cpp
题目: Given a collection of integers that might contain duplicates, nums, return all possible subsets. ...
- 【Sort Colors】cpp
题目: Given an array with n objects colored red, white or blue, sort them so that objects of the same ...
- 【Sort List】cpp
题目: Sort a linked list in O(n log n) time using constant space complexity. 代码: /** * Definition for ...
- 【Path Sum】cpp
题目: Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up ...
- 【Symmetric Tree】cpp
题目: Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). F ...
- 【Same Tree】cpp
题目: Given two binary trees, write a function to check if they are equal or not. Two binary trees are ...
随机推荐
- WIn10 电脑运行Docker
参考地址: https://www.cnblogs.com/linjj/p/5606687.html https://docs.docker.com/engine/reference/commandl ...
- zabbix文档3.4-7配置
zabbix文档3.4-7配置 1 主机和主机组 典型的Zabbix主机是您希望监视的设备(服务器,工作站,交换机等). 创建主机是Zabbix中首个监控任务之一.例如,如果要监视服务器"x ...
- springMvc-视图模型封装及注解参数
1.视图模型封装,ModelAndView可以向页面返回视图的同时吧模型也传入页面 2.注解参数,springMvc很好的地方在于简单,高效,@RequestParam注解能非常好的取得页面参数 代码 ...
- 【BZOJ1257】[CQOI2007] 余数之和(数学题)
点此看题面 大致题意: 求\(\sum_{i=1}^nk\%i\). 关于除法分块 这是一道除法分块的简单应用题. 式子转换 显然\(k\%i\)是一个很难处理的项. 于是我们就要使用使用一个常用的套 ...
- 【CF739E】Gosha is hunting(WQS二分套WQS二分)
点此看题面 大致题意: 你有两种捕捉球(分别为\(A\)个和\(B\)个),要捕捉\(n\)个神奇宝贝,第\(i\)个神奇宝贝被第一种球捕捉的概率是\(s1_i\),被第二种球捕捉的概率是\(s2_i ...
- PS 厘米与像素切换
方法一: 快捷键 ctrl + r 打开标尺将鼠标放在标尺刻度上右键 出现菜单里修改即可: 方法二: 编辑---首选项---单位与标尺 修改即可:
- Being a Good Boy in Spring Festival(博弈)
Being a Good Boy in Spring Festival Problem Description一年在外 父母时刻牵挂春节回家 你能做几天好孩子吗寒假里尝试做做下面的事情吧 陪妈妈逛一次 ...
- UVA1629 Cake slicing
题目传送门 直接暴力定义f[x1][y1][x2][y2]是使对角为\((x1, y1),(x2, y2)\)这个子矩形满足要求的最短切割线长度 因为转移顺序不好递推,采用记忆化搜索 #include ...
- Cobbler自动安装的Linux系统ssh无法进入
Linux ssh登陆老提示“permission denied,please try again” ,但是iptables已经关掉了 修改/etc/ssh/sshd_config文件.找如下的一句 ...
- Java基础面试操作题:读取该文件内容,并按照自然顺序排序后输出到 另一个文件中
package com.swift; import java.io.FileInputStream; import java.io.FileNotFoundException; import java ...