5

それで、数独を解くという大学の課題があります... アルゴリズム X とダンシング アルゴリズムについて読みましたが、役に立ちませんでした。

私はバックトラックでそれを作る必要があります。ウィキペディアから提供された場所の数字を使用して、2 次元配列のインデックスの一部をハードコーディングしました (したがって、解決可能であると確信しています)。

私が得たコードは次のとおりです。

public void solveSudoku(int row, int col)
   {
      // clears the temporary storage array that is use to check if there are
      // dublicates on the row/col
      for (int k = 0; k < 9; k++)
      {
         dublicates[k] = 0;
      }
      // checks if the index is free and changes the input number by looping
      // until suitable
      if (available(row, col))
      {
         for (int i = 1; i < 10; i++)
         {
            if (checkIfDublicates(i) == true)
            {
               board[row][col] = i;
               if (row == 8)
                  solveSudoku(0, col + 1);
               else if (col == 8)
                  solveSudoku(row + 1, 0);
               else
                  solveSudoku(row, col + 1);

               board[row][col] = 0;
            }
         }
      }
      // goes to the next row/col
      else
      {
         if (row == 8)
            solveSudoku(0, col + 1);
         else if (col == 8)
            solveSudoku(row + 1, 0);
         else
            solveSudoku(row, col + 1);
      }
   }

   /**
    * Checks if the spot on the certain row-col index is free of element
    * 
    * @param row
    * @param col
    * @return
    */
   private boolean available(int row, int col)
   {
      if (board[row][col] != 0)
         return false;
      else
         return true;
   }

   /**
    * Checks if the number given is not already used in this row/col
    * 
    * @param numberToCheck
    * @return
    */
   private boolean checkIfDublicates(int numberToCheck)
   {
      boolean temp = true;
      for (int i = 0; i < dublicates.length; i++)
      {
         if (numberToCheck == dublicates[i])
         {
            temp = false;
            return false;
         }
         else if (dublicates[i] == 0)
         {
            dublicates[i] = numberToCheck;
            temp = true;
            return true;
         }
      }
      return temp;
   }

私はStackOverflowを取得しています

// goes to the next row/col
          else
          {
             if (row == 8)
                solveSudoku(0, col + 1);
             else if (col == 8)
                solveSudoku(row + 1, 0);
             else
                solveSudoku(row, col + 1);
          }

つまり、ある時点で再帰を停止する必要がありますが、その方法がわかりません! 関数に他の間違いを見つけた場合は、solve()お知らせください。「バックトラック」のことを完全に理解しているかどうかわからないので...

4

4 に答える 4

3

たとえば、現在の再帰の深さを追跡している場合は、再帰を停止できます

public void solveSudoku(int row, int col, int recursionDepth) {
    // get out of here if too much
    if (recursionDepth > 15) return;

    // regular code...
    // at some point call self with increased depth
    solveSudoku(0, col + 1, recursionDepth + 1);
}

また、solve() 関数で他の間違いを見つけた場合は、お知らせください。

コードが多すぎます:)

于 2012-11-14T11:01:44.787 に答える
3

これは、私が過去にこれを行った大まかな方法​​です。

Whenever all the definite moves have been taken and there is a choice of equally good next moves:
    copy your grid data structure and push it onto a stack.
    take the first candidate move and continue solving recursively
    Whereever you get stuck:
         pop the saved grid off the stack
         take the next candidate move.
于 2012-11-14T11:03:06.780 に答える
1

DancingLinksとAlgorithmXが役に立たなかったとあなたが言う理由はわかりません。
アルゴリズムXが解決するように設計されている正確なカバー問題のインスタンスに数独をマッピングできなかったということですか?
それとも、それはあなたが必要とするものに対してあまりにも複雑なアプローチであるということですか?

前者の場合は、次のことを確認してください。KnuthのDancingLinksAlgorithmを実装するJavaの数独ソルバー。それは非常に明確であり、背後にある理由も説明しています。

NBアルゴリズムXはバックトラッキングアルゴリズムであるため、それが唯一の要件である場合は、このアプローチを確実に使用できます。

これがお役に立てば幸いです。

于 2012-11-15T13:40:53.337 に答える
1

私はより簡単な方法でそれを作りました:

public void solve(int row, int col)
   {
      if (row > 8)
      {
         printBoard();
         System.out.println();
         return;
      }
      if (board[row][col] != 0)
      {
         if (col < 8)
            solve(row, col + 1);
         else
            solve(row + 1, 0);
      }
      else
      {
         for (int i = 0; i < 10; i++)
            if (checkRow(row, i) && checkCol(col, i))
                  //&& checkSquare(row, col, i))
            {
               board[row][col] = i;
               if (col < 8)
                  solve(row, col + 1);
               else
                  solve(row + 1, 0);
            }
         board[row][col] = 0;
      }
   }

   private boolean checkRow(int row, int numberToCheck)
   {
      for (int i = 0; i < 9; i++)
         if (board[row][i] == numberToCheck)
            return false;

      return true;
   }

   private boolean checkCol(int col, int numberToCheck)
   {
      for (int i = 0; i < 9; i++)
         if (board[i][col] == numberToCheck)
            return false;

      return true;
   }
于 2012-11-15T12:26:50.663 に答える