leetcode - [37. 解数独]
题目大意
编写一个程序,通过已填充的空格来解决数独问题。一个数独的解法需遵循如下规则:
- 数字 1-9 在每一行只能出现一次。
- 数字 1-9 在每一列只能出现一次。
- 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 ‘.’ 表示。
解题思路
- 给出一个数独谜题,要求解出这个数独
- 解题思路 DFS 暴力回溯枚举。数独要求每横行,每竖行,每九宫格内,
1-9
的数字不能重复,每次放下一个数字的时候,在这 3 个地方都需要判断一次。 - 另外找到一组解以后就不需要再继续回溯了,直接返回即可。
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <iostream>
#include <vector>
using namespace std;
const int SodukuSize = 9;
bool row_mask[SodukuSize][SodukuSize];
bool col_mask[SodukuSize][SodukuSize];
bool area_mask[SodukuSize][SodukuSize];
bool initSudokuMask(vector<vector<char>> &board)
{
//重置内存
memset(row_mask, false, sizeof(row_mask));
memset(col_mask, false, sizeof(col_mask));
memset(area_mask, false, sizeof(area_mask));
//检查每一行和列
for (int r = 0; r < board.size(); r++)
{
for (int c = 0; c < board[r].size(); c++)
{
if (!isdigit(board[r][c]))
{
continue;
};
int idx = board[r][c] - '0' - 1;
//check the rows/cols/areas
int area = (r / 3) * 3 + (c / 3);
if (row_mask[r][idx] || col_mask[c][idx] || area_mask[area][idx] )
{
return false;
}
row_mask[r][idx] = col_mask[c][idx] = area_mask[area][idx] = true;
}
}
return true;
}
bool recursiveSudoKu(vector<vector<char>>& board ,int row, int col)
{
if(row >= SodukuSize)
{
return true;
}
if(col >= SudukuSize)
{
return recursiveSudoKu(board, row + 1, 0);
}
if(board[row][col] != '.')
{
return recursiveSudoku(board,row,col+1);
}
//为空单元格选择一个数字
int area;
for(int i = 0; i < SudukuSize;i++)
{
area = (row / 3) * 3 + (col / 3);
if (row_mask[row][i] || col_mask[col][i] || area_mask[area][i] )
{
continue;
}
//设置数字并递归求解
board[row][col] = i + '1';
row_mask[row][i] = col_mask[col][i] = area_mask[area][i] = true;
if (recursiveSudoKu(board, row, col + 1) == true)
{
return true;
}
//回溯
board[row][col] = '.';
row_mask[row][i] = col_mask[col][i] = area_mask[area][i] = false;
}
return false;
}
void solveSudoku(vector<vector<char> > &board)
{
if (initSudokuMask(board) == false)
{
return;
}
recursiveSudoKu(board, 0, 0);
}
int main(int argc, char **argv)
{
return 0;
}