根据给定的不规则区域求解数独
给定两个大小为N * N的矩阵sudoku[][]和region[][] ,任务是根据给定的不规则区域填充给定的 Sudoku。如果无法填充sodoku[][]矩阵,则打印-1 。以下是矩阵的定义:
数独矩阵(sudoku[][]):它是一个N×N矩阵,包含从0 到 N的元素,其中0表示需要填充以解决数独问题的空单元格。
解决数独的规则:
- 每个 Row 和 column 必须具有从1 到 N的唯一编号。
- 每个区域必须具有从1 到 N的唯一编号。
区域矩阵(region[][]):它是一个N×N矩阵,包含表示数独区域的字符。矩阵中相同的字符表示数独的一个区域。
例子:
Input: sudoku[][] = {
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 4, 0, 0},
{3, 0, 0, 6, 0, 0, 0},
{0, 0, 0, 0, 6, 0, 1},
{5, 0, 0, 0, 0, 0, 3},
{0, 0, 1, 0, 0, 0, 2},
{2, 0, 0, 0, 0, 0, 5} }
region[][] = {
{r, r, r, b, b, b, b},
{g, r, r, r, r, b, o},
{g, g, g, g, b, b, o},
{p, p, g, o, o, o, o},
{p, p, g, d, o, l, l},
{p, p, p, d, l, l, l},
{d, d, d, d, d, l, l} }
Output:
7 1 3 4 5 2 6
1 6 5 2 4 3 7
3 5 2 6 1 7 4
4 2 7 3 6 5 1
5 7 4 1 2 6 3
6 3 1 5 7 4 2
2 4 6 7 3 1 5
Explanation:
Unsolved Sudoku Puzzle with the regions:
Solved Sudoku puzzle with the regions:
Input: sudoku[][] = {
{ 0, 0 },
{ 0, 1 } },
region[][] = {
{r, r},
{b, b}}
Output:
1 2
2 1
Explanation:
Elements of the row of the output matrix: {1, 2}, {2, 1}
Elements of the column of the matrix: {1, 2}, {2, 1}
Elements of the same regions of the matrix: {1, 2}, {2, 1}
Since it contains unique elements in the rows, columns and regions.
Therefore, it is a valid solution of the Sudoku.
方法:这个想法是使用回溯来解决数独问题,方法是递归地将编号分配给空单元格,并在违反任何规则时回溯,即每行、列和区域必须具有从1 到 N的唯一编号。下面是借助步骤的插图:
- 创建一个函数来检查分配给单元格的数字是否安全:
- 要检查当前行和列,请遍历行和列并检查分配的数字是否存在于单元格中。
- 要检查数字是否存在于当前区域,请使用广度优先搜索。
- 遍历网格以检查任何未分配的单元格并将值从1 分配到 N并检查分配的数字是否安全。如果分配的号码不安全,则回溯未分配的单元格。
- 如果所有未分配的单元格都分配了某个数字,则打印数独。否则,没有解决办法。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Grid dimension
const int N = 2;
// Function to check if the number to be present
// in the current cell is safe or not
bool issafe(int sudoku[N][N], int i, int j, int n,
int number, char region[N][N])
{
// Check if the number is present in
// i-th row or j-th column or not
for (int x = 0; x < n; x++) {
if (sudoku[x][j] == number
|| sudoku[i][x] == number) {
return false;
}
}
// Check if the number to be filled
// is safe in current region or not
char r = region[i][j];
// Initialize the queue for the BFS
queue > q;
// Insert the current cell into queue
q.push(make_pair(i, j));
// Check if the neighbours cell is
// visited or not
int visited[N][N];
// Initialize visited to 0
memset(visited, 0, sizeof visited);
// Mark current cell is visited
visited[i][j] = 1;
// Performing the BFS technique
// Checking for 4 neighbours at a time
while (!q.empty()) {
// Stores front element of the queue
pair front = q.front();
// Pop top element of the queue
q.pop();
// Check for neighbours cell
if (front.first + 1 < N
&& region[front.first + 1][front.second] == r
&& !visited[front.first + 1][front.second]) {
// If already contains the same number
if (sudoku[front.first + 1][front.second]
== number) {
return false;
}
q.push(make_pair(front.first + 1,
front.second));
// Mark as neighbour cell as visited
visited[front.first + 1][front.second] = 1;
}
// Checking for 2nd neighbours
if (front.first - 1 >= 0
&& region[front.first - 1][front.second] == r
&& !visited[front.first - 1][front.second]) {
// If neighbours contains the same number
if (sudoku[front.first - 1][front.second]
== number) {
return false;
}
// Insert neighbour cell into queue
q.push(make_pair(front.first - 1,
front.second));
// Mark neighbour cell as visited
visited[front.first - 1][front.second] = 1;
}
// Checking for 3rd neighbours
if (front.second + 1 < N
&& region[front.first][front.second + 1] == r
&& !visited[front.first][front.second + 1]) {
// If neighbours contains the same number
if (sudoku[front.first][front.second + 1]
== number) {
return false;
}
// Insert neighbour cell into queue
q.push(make_pair(front.first,
front.second + 1));
// Mark neighbour cell as visited
visited[front.first][front.second + 1] = 1;
}
// Checking for 4th neighbours
if (front.second - 1 >= 0
&& region[front.first][front.second - 1] == r
&& !visited[front.first][front.second - 1]) {
// If neighbours contains the same number
if (sudoku[front.first][front.second - 1]
== number) {
return false;
}
// Insert neighbour cell into queue
q.push(make_pair(front.first,
front.second - 1));
// Mark neighbour cell as visited
visited[front.first][front.second - 1] = 1;
}
}
return true;
}
// Recursive function to solve the sudoku
bool solveSudoku(int sudoku[N][N], int i, int j,
int n, char region[N][N])
{
// If the given sudoku already solved
if (i == n) {
// Print the solution of sudoku
for (int a = 0; a < n; a++) {
for (int b = 0; b < n; b++) {
cout << sudoku[a][b] << " ";
}
cout << endl;
}
return true;
}
// If the numbers in the current row
// already filled
if (j == n) {
return solveSudoku(sudoku, i + 1, 0, n, region);
}
// If current cell is not empty
if (sudoku[i][j] != 0) {
return solveSudoku(sudoku, i, j + 1, n, region);
}
else {
// Iterate over all possible value of numbers
for (int number = 1; number <= n; number++) {
// If placing the current number is safe
// in the current cell
if (issafe(sudoku, i, j, n, number, region)) {
// Update sudoku[i][j]
sudoku[i][j] = number;
// Fill the remaining cells of the sudoku
bool rest
= solveSudoku(sudoku, i,
j + 1, n, region);
// If remaining cells has been filled
if (rest == true) {
return true;
}
}
}
// Otherwise No Solution
sudoku[i][j] = 0;
return false;
}
}
// Driver Code
int main()
{
// Given sudoku array
int sudoku[N][N] = {
{ 0, 1 },
{ 0, 0 }
};
// Given region array
char region[N][N] = {
{ 'r', 'r' },
{ 'b', 'b' }
};
// Function call
int ans = solveSudoku(
sudoku, 0, 0, N, region);
// No answer exist
if (ans == 0) {
cout << "-1";
}
return 0;
}
Javascript
2 1
1 2
时间复杂度: O(N N2 )
辅助空间: O(N 2 )