回溯算法--解数独

编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 ‘.’ 表示。
第一次接触回溯算法,道理不难,就是代码比较长

int[][]col=new int[9][10];//记录每一列存在的数
  int [][]row=new int[9][10];//记录每一行存在的数
  int [][]box=new int[9][10];//记录每一个3*3出现的数
  boolean ok=false;//完成数独
    //初次遍历,把已有的数记录下来
  void solveSudoku(char[][]board)
  {
   for(int i=0;i<9;i++)
    for(int j=0;j<9;j++)
    {
     if(board[i][j]!='.')
     {
      int d=Integer.valueOf(board[i][j]+"");
      place(board,i,j,d);
     }
    }
   traceback(board, 0, 0);
  }
  //放置一个数,更新行列框内的值
  void place(char[][]board,int i,int j,int d)
  {
   col[j][d]=1;
   row[i][d]=1;
   box[(i/3)*3+j/3][d]=1;//得到对应的3*3的框号
            board[i][j]=(char)(d+'0');//要加上'0'不然会转成ASCII码对应的字符
  }
  //回溯算法
  void traceback(char[][]board, int i,int j)
  {
   if(board[i][j]=='.')//对自己填的格子进行回溯
   {
    for(int k=1;k<10;k++)//从1到9逐个填入看能否满足条件
    {
     if(couldplace(board,i,j,k))
     {
      place(board,i,j,k);//放入k值
      placenext(board,i,j);/*进行下一个格子的判断,如果一直满足条件,会一直
      由此进入下一个格子,直到最后一个格子*/
      if(!ok)/*没有达到最后一个格子,但来到这一步,说明出现一次遍历k之后不能找到解,
      删除最后放入的格子*/
      remove(board, i, j,k);//删除当前格子的值
     }
    }
   }
   else placenext(board,i,j);//题目填充好,直接进入放下一个数
  }
  //能否放置一个数
  boolean couldplace(char[][]board,int i,int j,int k)
  {
   int a=col[j][k]+row[i][k]+box[(i/3)*3+j/3][k];
   if(a>0)
    return false;
   else return true;
  }
  //放置下一个数,判断是否换行,结束
  void placenext(char[][]board,int i,int j)
  {
   if(i==8&&j==8)//填完
    ok=true;
   else if(j==8)//换行
    traceback(board,i+1,0);
   else traceback(board,i, j+1);//下一个
  }
  //删除该数
  void remove(char[][]board,int i,int j,int d)
  {
   col[j][d]=0;
   row[i][d]=0;
   box[(i/3)*3+j/3][d]=0;
   board[i][j]='.';
  }
发布了45 篇原创文章 · 获赞 4 · 访问量 1029

猜你喜欢

转载自blog.csdn.net/weixin_43838915/article/details/105683804