📜  根据给定的不规则区域求解数独

📅  最后修改于: 2022-05-13 01:56:08.692000             🧑  作者: Mango

根据给定的不规则区域求解数独

给定两个大小为N * N的矩阵sudoku[][]region[][] ,任务是根据给定的不规则区域填充给定的 Sudoku。如果无法填充sodoku[][]矩阵,则打印-1 。以下是矩阵的定义:

数独矩阵(sudoku[][]):它是一个N×N矩阵,包含从0 到 N的元素,其中0表示需要填充以解决数独问题的空单元格。
解决数独的规则:

  • 每个 Row 和 column 必须具有从1 到 N的唯一编号。
  • 每个区域必须具有从1 到 N的唯一编号。

区域矩阵(region[][]):它是一个N×N矩阵,包含表示数独区域的字符。矩阵中相同的字符表示数独的一个区域。

例子:

方法:这个想法是使用回溯来解决数独问题,方法是递归地将编号分配给空单元格,并在违反任何规则时回溯,即每行、列和区域必须具有从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 )