数据递归在回溯时有问题。 (蛮力)

时间:2012-03-01 00:18:12

标签: java algorithm recursion sudoku

  

可能重复:
  Sudoku solver in java, using backtracking and recursion

我正在创建一个程序,它将使用递归和暴力解决数独。我的关键问题是,我不明白我是如何能够令人难以置信地让它重新陷入困境。

该程序的一般算法如下:

  1. 查找数独中的零个数。

  2. 在第一个0的位置(getNextEmpty方法执行此操作),插入一个数字(insertnumber检查以确保值符合数独规则,如果存在则返回true)。

  3. 然后我进行递归调用,当没有更多的零时结束(n是零的数量)。

  4. 如果程序达到了卡住的程度,我必须回溯才能更改。但这怎么可能呢?

  5. Cell类实际上以[row,column]格式的数组的形式保存要调整的单元格的位置。它具有返回与该单元格关联的行,列或较小网格的方法。

    我不是要求手持或所有代码,只要在正确的方向上轻推就足够了,因为我对理解递归有合法的兴趣。

    public static int[][] getSolution(int[][] grid) {
        for (int i = 0; i < 9; i++) {
            System.arraycopy(grid[i], 0, SolveSudoku.grid[i], 0, 9);
        }// end for
        int n = getZeroes();
        return getSolution(n);
    }//end getSolution
    
    private static int[][] getSolution(int n) {
        if (n == 0) {
            return grid;        
        }//end if
        Cell cell = getNextEmpty();
        boolean fits = false;
        for (int i = 0; i <= 9; i++) {
            fits = insertNumber(cell, i);
            if (fits) {
                break;
            }else {
                //I do not understand what I should do here
            }
        }//end for
        return getSolution(n - 1);
    }//end getSolution
    

2 个答案:

答案 0 :(得分:2)

向正确的方向轻推。您的方法需要稍微调整,因为您没有跟踪解决网格所需的所有信息。

private static int[][] getSolution(int n) {
    if (n == 0) {
       return grid;        
    }//end if

    Cell cell = getNextEmpty();
    boolean fits = false;
    for (int i = 0; i <= 9; i++) {
        fits = insertNumber(cell, i);
        if (fits) {
            break; // means i fits in Cell
        } else {
            // i doesn't fit... try the next i
            // don't need to do anything
        }
    }//end for
    if (!fits) {
        // There are no numbers that fit in this Cell
        // What should happen?
        // Did I make a bad guess?
        // How do I BACKTRACK and correct a previous guess?
    }
    return getSolution(n - 1);
}//end getSolution

答案 1 :(得分:1)

通常在递归暴力中,您使用类似于以下代码的语法。之所以这样做是因为你可以在做完任何动作后计算出来,那就是新的“起始位置”。 所以它类似于:

private void Guess(int[][] grid)
{
    if(/**grid is a solution **/)
        //signal success
    else
    {
        if(/*seed out any bad, unacceptable answers you may have missed*/)
            return;//this includes cases when there are no more zeros
        //for every possible move,
        //make a modified grid, with one move done, and call
        Guess(ModifiedGrid);//for every possible move, generally you can modify
        //grid itself, because its passed by value
    }
}