ブルートフォースバックトラッキングを使用して数独グリッドを解決する非常に単純なアルゴリズムを実装しようとしています。私が直面している問題は、数独グリッドを表す 2 次元配列の空のセルの行と列に対応するとというSudoku
クラスの 2 つのインスタンス変数を実装に含めたことです。row
col
私のsolve()
メソッドが実行されると、最初に空のセルがないかどうかがチェックされます。この場合、パズルはすでに完成しています。それ以外の場合、同じメソッドが空のセルの行と列をインスタンス変数row
とグリッドを含むオブジェクトにcol
割り当てます。Sudoku
その後、 for ループは、メソッド呼び出しによって空のセルに配置できる数字を検証しますisSafe(int n)
(このメソッドは、パズルの制約が満たされているかどうかを確認します。完全に機能することを保証できます)。そのため、メソッドは空のセルに数値を配置し、オブジェクトでメソッドisSafe()
を再帰的に呼び出します。solve()
Sudoku
満たすことができない制約にヒットした場合0
、最後row
にa を再割り当てし、col
それが満たされました。ここで問題が発見されました!プログラムは常に変数row
とcol
変数を更新しているため、古いインスタンスは再帰呼び出しごとに失われます。プログラムがバックトラックしたときにアクションを取り消すことができるように、この値を保存する方法を見つけようとしています。col
それぞれをスタックにプッシュすることを考えrow
ましたが、どこに行けばいいのか本当にわかりません。
この問題にアプローチする簡単な方法を誰か教えてもらえますか? クラス全体は含まれていません。役立つと思われる場合はお知らせください。投稿します。
class Sudoku {
int SIZE, N, row, col;
int Grid[][];
public boolean solve() {
if (!this.findNextZero()) return true;
for (int num = 1; num <= 9; num++) {
if (isSafe(num)) {
this.Grid[this.row][this.col] = num;
if (this.solve()) return true;
this.Grid[this.row][this.col] = 0;
// this.Grid[oldRow][oldCol] = 0;
}
}
return false;
}
public boolean findNextZero() {
for (int i = 0; i < this.N; i++) {
for (int j = 0; j < this.N; j++) {
if (this.Grid[i][j] == 0) {
this.row = i;
this.col = j;
return true;
}
}
}
return false;
}
public boolean isSafe(int num) {
return !this.usedInRow(num)
&& !this.usedInColumn(num)
&& !this.usedInBox(num);
}
スタックを実装する場合、次のことは理にかなっていますか? 操作の後、および整数をスタックにfindNextZero()
プッシュします。これを続けてから、次のコード行を変更しますrow
col
this.Grid[this.row][this.col] = 0;
のようなものに
this.Grid[s.pop][s.pop] = 0;
これは合理的なアプローチですか?