【问题标题】:Solving a Sudoku field with Recursion and Backtracking in C在 C 中使用递归和回溯解决数独领域
【发布时间】:2021-07-15 14:11:36
【问题描述】:

我的挑战是使用递归和回溯解决给定的数独字段。我们已经有一些代码,但我们不知道如何实现回溯。这是我们的代码:

int solve( int row, int col ) {
    if (getValueFromField(row, col) != 0) {
        if (col < 8) {
            return solve(row, col + 1);
        }
        if (col == 8) {
            return solve(row + 1, 0);
        }
        if (col == 8 && row == 8) {
            return 1;
        }
    } else {
        for (int i = 1; i <= 9; i++) {
            if (checkValueInField(i, row, col)) {
                setValueInField(i, row, col);
                if (solve(row, col)) {
                    continue;
                }
                return solve(row, col + 1);
            }
        }
        removeValueFromField(row, col);
        return 0;
    }
    return -1;
}

removeValueFromField()setValueInField() 等方法自行解释。如果没有,我可以向你解释他们是做什么的。

您对如何在此处实施回溯有任何想法吗? 你好! 拉斐尔

【问题讨论】:

    标签: c recursion backtracking sudoku recursive-backtracking


    【解决方案1】:

    您必须保存之前所做的检查,例如在列表中 每个单元格的可能值。最初,所有列表都包含 数字 1-9。在初始化时,给定的列表 数独中的单元格减少到一个成员。

    然后,主要算法是对所有单元格的循环,您可以实现它 作为递归,就像在你的代码中一样。在这个循环中,所有数独约束 应用于每个列表,并删除不兼容的情况。 例如:假设 cell(1,1) 为 '1',那么我们可以从第 1 行第 1 列的所有列表中删除 1, 块 (1,1) 等。我们循环直到没有不兼容的情况存在。 如果列表中的一个折叠到零长度,则数独是无法解决的。

    如果此时 (A) 两个或多个列表的长度保持大于 1,我们 从这些列表之一中选择一种可能性(比如 p),然后开始 再次循环。如果事实证明这是无法解决的,我们从列表中删除 p, 回到(A)(这是回溯)并尝试第二种可能性,等等。 最终,我们将达到一个阶段,除了一个列表之外,所有列表的长度都为 1。 如果最后一个列表的长度 > 0,则数独是可解的。

    这是一个简化版本,它只是找到了一种可能的解决方案。 您必须自己编写原型函数。

    int getListLength(row, col); // number of possible values for this cell, 0...9
    
    void checkConstrains();         // loop all sets (rows, columns, blocks)
                                    // and find lists with one element. Remove
                                    // this element from all other lists in the set.
                                    // Repeat until no duplicates are found.
                            
    int *savelist(row, col);        // make a copy of the list
    void setlist(row, col, k);      // set list of cell to { k }
    getstate(), setstate(s);        // save and set state of the game, ie. all lists
                                    
    
    
    int solve( int row, int col ) {
            int length = getListLength(row, col);
            if(length == 0)
                    return 0; // unsolveable
            
            // this is your recursion step slightly
            // reordered to avoid row-overflow
            
            if (col == 8 && row == 8) {
                    return 1;
            }
            
            int next_row, next_col;
            if(col < 8) {
                    next_row = row;
                    next_col = col + 1;
            } else {
                    next_row = row + 1;
                    next_col = 0;
            }
            
            if(length == 1) {
                    return solve(next_row, next_col);
            }
            
            // if we reach this step: length > 1
            checkConstrains();
            
            // length might have changed
            length = getListLength(row, col);
            
            if(length == 0)
                    return 0;
            if(length == 1)
                    return solve(next_row, next_col);
            
            // still: length > 1
            // backtracking stage
            
            int* list = savelist(row, col);
            sudoku s = getstate();
            
            for(int i = 0; i < length; i++) {
                    setstate(s);
                    setlist(row, col, list[i]);
                    if(solve(row, col))
                            return 1;
            }
            // all elements from list failed-->unsolveable
            // free list and s
            return 0;
    }
             
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-16
      • 2014-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多