微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 C++ 中创建数独求解器时打印错误

如何解决在 C++ 中创建数独求解器时打印错误

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

#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,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,board,grid,row,col);
        return;
    }

    if(board[x][y] != '.'){
        solver(x,y + 1,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,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> > 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,col);
}

int main(){

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

    return 0;
}

解决方法

solver 的第一次调用是:

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

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

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

即:它调用 solver(0,1,col)。然后 board[0][1]'.',而 x 不是 9 并且 y 不是 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,col);
        board[x][y] = '.';
        grid[{x/3,y/3}][i] = 0;
        row[x][i] = 0;
        col[y][i] = 0;
    }
}

因此,如果我们内联前两个调用,我们可以用上面的替换 solver(0,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,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 并打印更新的板,但您只能通过执行 sudokuSolver 的路径返回 board[x][y] = '.';

不知道如何更好地解释,也许使用调试器现场观看它会更有说服力。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。