为什么数独回溯卡住了?

如何解决为什么数独回溯卡住了?

| 我正在写数独回溯解算器,但是卡住了,我不明白为什么。我认为我的递归调用很好。我缺少什么? 输入是从input.txt文件中读取的,其中网格的初始布局为一行: input.txt:
004020000201950070090004852005490001006000900800051300958100020010072608000080500
编辑:我的意思是“卡住”不是完成对网格的求解 这是一个示例输出
current move count is 6
3 6 4 7 2 8 1 9 0 
2 0 1 9 5 0 0 7 0 
0 9 0 0 0 4 8 5 2 
0 0 5 4 9 0 0 0 1 
0 0 6 0 0 0 9 0 0 
8 0 0 0 5 1 3 0 0 
9 5 8 1 0 0 0 2 0 
0 1 0 0 7 2 6 0 8 
0 0 0 0 8 0 5 0 0 
程序:
package sudoku;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;




public class Main {

 static boolean checkRow( int row,int num,int grid[][])
   {
      for( int col = 0; col < 9; coL++ )
         if( grid[row][col] == num )
            return false ;

      return true ;
   }

static boolean checkCol( int col,int grid[][] )
   {
      for( int row = 0; row < 9; row++ )
         if( grid [row][col] == num )
            return false ;

      return true ;
   }


static boolean checkBox( int row,int col,int grid[][] )
   {
      row = (row / 3) * 3 ;
      col = (col / 3) * 3 ;

      for( int r = 0; r < 3; r++ ){
         for( int c = 0; c < 3; c++ ){
            if( grid[row+r][col+c] == num )
            return false ;          
         }
      }
      return true ;
   }


  static void printSolvedGrid(int grid[][]){

       for (int i=0; i<grid.length; i++){
            for (int j=0; j<grid.length;j++){
              System.out.print(grid[i][j]+\" \");
            } System.out.println();
        }

  }


   static int moveCounter=0;

   static boolean solve(int row,int [][]grid){

       if (row>=grid.length){

           System.out.println(\"solution found\");
           printSolvedGrid(grid);

       }

       if( grid[row][col] != 0 ){
            next( row,col,grid ) ;
       }

       else {
         // Find a valid number for the empty cell
         for( int num = 1; num < 10; num++ )
         {
            if( checkRow(row,num,grid) && checkCol(col,grid) && checkBox(row,grid) )
            {
               grid[row][col] = num ;
               moveCounter++;
               System.out.println(\"current move count is \" + moveCounter);
               printSolvedGrid(grid);
               next( row,grid );
               return true;
            }
         }

       }
       return false;
    }


  public static void next( int row,int [][] grid )
   {
      if( col < 8 ) //pass to next col
         solve( row,col + 1,grid ) ;
      else //pass to next row 
         solve( row + 1,grid ) ;
   }







    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new FileReader(new File(\"input.txt\")));
        char gridChar[] = br.readLine().tochararray();

       int [][] grid = new int [9][9];

        int gridCharIndex=0;
        for (int i=0; i<grid.length; i++){
            for (int j=0; j<grid.length;j++){

              grid[i][j]= Integer.parseInt(gridChar[gridCharIndex++]+\"\");
              System.out.print(grid[i][j]+\" \");
            } System.out.println();
        }

        solve(0,grid);
        }//end method main
    }//end class Main
    

解决方法

        关于为什么不发生回溯的一个关键提示是,您有一个名为
solve
的布尔函数,其返回值根本没有被使用。 在此循环中:
     for( int num = 1; num < 10; num++ )
     {
        if( checkRow(row,num,grid) && checkCol(col,grid) && checkBox(row,col,grid) )
        {
           grid[row][col] = num ;
           moveCounter++;
           System.out.println(\"current move count is \" + moveCounter);
           printSolvedGrid(grid);
           next( row,grid );
           return true;
        }
     }
您找到当前单元格的合适候选者,将其插入,然后致电
next
next
然后调用
solve
,但是在返回后,您仅假设这是正确的选择,而
return true;
则因此
solve
返回false时,您将不注意它,而不会尝试该单元格的其他选择。     ,        您的解决方案陷入困境,因为在使用递归时(优化代码不是很容易,您可以使其尾部递归,这样就不会建立堆栈,但是您却没有。尽管那是一个单独的问题)您实际上并没有检查每个可能的分支。 让我给您一个示例场景,其中您的代码会卡住: 考虑一下数独难题的左上角:
0 0 3
4 5 6
7 8 9
0 2
您的算法将检查平方[0] [0]并发现1是合适的拟合。然后它将继续检查正方形[0] [1],并发现1不适合。因此,当检查2时,也会发现该列中已经存在2。其余的数字都在框中。因此它被卡住了,因为它永远不会将其步骤追溯到先前的决策。 应该怎么办?它应该递归,它应该能够退后并更改导致这种情况的决策。 \“ True \”递归(即检查一个有效的递归树的所有可能选项)将能够“撤消”最后一个决定并尝试下一个决定,即发现2可以位于左上角,然后继续。     ,        固定: 我拿走了布尔值和return语句:) 顺便说一句,看来我原来的测试用例没有解决方案,但是这两个输入确实产生了一个: input1.txt
900576813630090002005000900001004730200000008076900500003000600400050091712869005 
input2.txt(这很难)
200609050604083000000700000048000200000010000001000490000001000000970103020408005 
码:
static void solve(int row,int col,int [][]grid){

       if (row>=grid.length){

           System.out.println(\"solution found\");
           printSolvedGrid(grid);
           System.exit(0);

       }

       if( grid[row][col] != 0 ){
            next( row,grid ) ;
       }

       else {
         // Find a valid number for the empty cell
         for( int num = 1; num < 10; num++ )
         {
            if( checkRow(row,grid) )
            {
               grid[row][col] = num ;
               moveCounter++;
               System.out.println(\"current move count is \" + moveCounter);
               printSolvedGrid(grid);
               next( row,grid );

            }
         }

         grid[row][col] = 0 ;
       }

    }
    ,        不确定“卡住”是什么意思,是代码被卡住还是无法解决难题。 简短地看一下它,我找不到代码有什么问题,但是与此同时,使用递归的方式并不是很正确,但是即使没有找到解决方案,它也应该运行。 但是还有其他解决数独难题的技术,X翼可能是最复杂的技术之一... 即使遵循您现在正在做的事情,您可能也需要多次进行这些测试... 编辑: 我运行您的代码,运行得很好,在最后一个阶段,它显示了:
current move count is 6
3 6 4 7 2 8 1 9 0 
2 0 1 9 5 0 0 7 0 
0 9 0 0 0 4 8 5 2 
0 0 5 4 9 0 0 0 1 
0 0 6 0 0 0 9 0 0 
8 0 0 0 5 1 3 0 0 
9 5 8 1 0 0 0 2 0 
0 1 0 0 7 2 6 0 8 
0 0 0 0 8 0 5 0 0 
然后它就完成了...它根本无法解决任何问题。 我想代替使用
row>=grid.length
作为终止条件,您应该遍历网格以查找是否还有“ 0”。在
row>=grid.length
的情况下,您应该重新开始:
solve(0,grid)
。 那可能仍然不能解决所有问题,但是肯定会走得更远。     

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

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?