【问题标题】:Print error while creating a sudoku solver in c++在 C++ 中创建数独求解器时打印错误
【发布时间】:2021-09-08 01:27:23
【问题描述】:

代码中的打印函数打印原始板而不是解决方案,而求解器函数打印表明原始板已更新到位的解决方案。如您所见,我通过引用函数传递了板,那么为什么调用打印函数后原始板没有更新?

#include <iostream>
#include <vector>
#include <map>
using namespace std;

int n = 9;

void print(vector<vector<char>>& board){
    for(int i = 0; i < 9; i++){
        for(int j = 0; j < n; j++){
            cout << board[i][j] << " ";
        }
        cout << endl;
    }
}

void solver(int x, int y, vector<vector<char>>& board, map< pair<int, int>, map<int, int> >& grid, vector<map<int, int>> row,vector<map<int, int>>& col){

    if(x == 9){
        for(int i = 0; i < 9; i++){
            for(int j = 0; j < n; j++){
                cout << board[i][j] << " ";
            }
            cout << endl;
        }
        return;
    }

    if(y == 9){
        solver(x + 1, 0, board, grid, row, col);
        return;
    }

    if(board[x][y] != '.'){
        solver(x, y + 1, board, grid, row,  col);
        return;
    }

    for(int i = 1; i <= 9; i++){
        if(!grid[{x/3, y/3}][i] && !row[x][i] && !col[y][i]){
            board[x][y] = i + '0';
            grid[{x/3, y/3}][i] = 1;
            row[x][i] = 1;
            col[y][i] = 1;
            solver(x, y + 1, board, grid, row, col);
            board[x][y] = '.';
            grid[{x/3, y/3}][i] = 0;
            row[x][i] = 0;
            col[y][i] = 0;
        }
    }

}

void solveSudoku(vector<vector<char>>& board) {
    //int n = board.size();
    vector< map<int, int> > row(n);
    vector< map<int, int> > col(n);
    map< pair<int, int>, map<int, int> > grid;

    for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
            if(board[i][j] != '.'){
                row[i][board[i][j] - '0'] = 1;
                col[j][board[i][j] - '0'] = 1;
                grid[{i/3, j/3}][board[i][j] - '0'] = 1;
            }
        }
    }
    solver(0, 0, board, grid, row, col);
}

int main(){

    vector<vector<char>> board =
    {{ '5','3','.','.','7','.','.','.','.'},
     {'6','.','.','1','9','5','.','.','.'},
     {'.','9','8','.','.','.','.','6','.'},
     {'8','.','.','.','6','.','.','.','3'},
     {'4','.','.','8','.','3','.','.','1'},
     {'7','.','.','.','2','.','.','.','6'},
     {'.','6','.','.','.','.','2','8','.'},
     {'.','.','.','4','1','9','.','.','5'},
     {'.','.','.','.','8','.','.','7','9'}};
    solveSudoku(board);
    cout << endl;
    print(board);

    return 0;
}

【问题讨论】:

  • 我发现你修改电路板的唯一地方是board[x][y] = i + '0';,下面的一些行通过board[x][y] = '.';重置了它
  • 仔细查看row 是如何传递给求解器的。
  • board[x][y] = '.'; 行是您所看到行为的原因。我没有仔细遵循求解器逻辑来确定这是否对求解器至关重要。
  • @463035818_is_not_a_number 就是回溯逻辑。但最终电路板最终在求解器函数中打印,因为它是边缘情况,然后返回。那么为什么板子(现在的解决方案)会更新?
  • @S.M.仍然没有解决问题。

标签: c++ recursion backtracking sudoku


【解决方案1】:

solver 的第一个电话是:

solver(0, 0, board, grid, row, col);

因为board[0][0] 不是'.',所以第一次调用只是

if(board[x][y] != '.'){
    solver(x, y + 1, board, grid, row,  col);
    return;
}

即:它调用solver(0,1,board,grid,row,col)。那么board[0][1]'.'x 不是9y 不是9 并且该调用执行:

for(int i = 1; i <= 9; i++){
    if(!grid[{x/3, y/3}][i] && !row[x][i] && !col[y][i]){
        board[x][y] = i + '0';
        grid[{x/3, y/3}][i] = 1;
        row[x][i] = 1;
        col[y][i] = 1;
        solver(x, y + 1, board, grid, row, col);
        board[x][y] = '.';
        grid[{x/3, y/3}][i] = 0;
        row[x][i] = 0;
        col[y][i] = 0;
    }
}

因此,如果我们内联前两个调用,我们可以将solver(0, 0, board, grid, row, col); 替换为上面的得到:

void solveSudoku(vector<vector<char>>& board) {
    //int n = board.size();
    vector< map<int, int> > row(n);
    vector< map<int, int> > col(n);
    map< pair<int, int>, map<int, int> > grid;

    for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
            if(board[i][j] != '.'){
                row[i][board[i][j] - '0'] = 1;
                col[j][board[i][j] - '0'] = 1;
                grid[{i/3, j/3}][board[i][j] - '0'] = 1;
            }
        }
    }

    size_t x = 0; 
    size_t y = 1;
    for(int i = 1; i <= 9; i++){
        if(!grid[{x/3, y/3}][i] && !row[x][i] && !col[y][i]){
            board[x][y] = i + '0';
            grid[{x/3, y/3}][i] = 1;
            row[x][i] = 1;
            col[y][i] = 1;
            solver(x, y + 1, board, grid, row, col);
            board[x][y] = '.';
            grid[{x/3, y/3}][i] = 0;
            row[x][i] = 0;
            col[y][i] = 0;
        }
    }    
}

这里board[0][1] 被分配了一个i + '0';,然后递归发生,然后board[0][1] 被重置为'.'。当深入递归的调用链时,可以应用相同的推理。每当你给board[x][y] 赋值时,它都会在solver 返回solveSudoku 之前被重置。当您是“递归的底部”时,您只能到达x == 9 并打印更新的板,但您只能通过执行board[x][y] = '.'; 的路径返回到sudokuSolver

不知道如何更好地解释,也许你用调试器看到它​​更有说服力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    • 2019-05-09
    • 1970-01-01
    • 2014-02-07
    • 1970-01-01
    相关资源
    最近更新 更多