[英]Solving a Sudoku field with Recursion and Backtracking in C
我的挑戰是用遞歸和回溯解決給定的數獨領域。 我們已經有一些代碼,但我們不知道如何實現回溯。 這是我們的代碼:
int solve( int row, int col ) {
if (getValueFromField(row, col) != 0) {
if (col < 8) {
return solve(row, col + 1);
}
if (col == 8) {
return solve(row + 1, 0);
}
if (col == 8 && row == 8) {
return 1;
}
} else {
for (int i = 1; i <= 9; i++) {
if (checkValueInField(i, row, col)) {
setValueInField(i, row, col);
if (solve(row, col)) {
continue;
}
return solve(row, col + 1);
}
}
removeValueFromField(row, col);
return 0;
}
return -1;
}
removeValueFromField()
、 setValueInField()
等方法可以自行解釋。 如果沒有,我可以向您解釋他們的工作。
您對如何在此處實施回溯有想法嗎? 問候! 拉斐爾
您必須將之前所做的檢查保存在每個單元格的可能值列表中。 最初,所有列表都包含數字 1-9。 初始化后,數獨中給定單元的列表減少為一個成員。
然后,主要算法是對所有單元格的循環,您可以將其實現為遞歸,就像在您的代碼中一樣。 在此循環中,所有數獨約束都應用於每個列表,並刪除了不兼容的情況。 例如:假設 cell(1,1) 為 '1',那么我們可以從第 1 行、第 1 列、塊 (1,1) 等的所有列表中刪除 1。我們循環直到沒有不兼容的情況存在。 如果列表之一折疊為零長度,則數獨是無法解決的。
如果在這一點 (A) 兩個或多個列表的長度保持大於 1,我們選擇其中一個列表的可能性之一(例如 p),並再次開始循環。 如果事實證明這是無法解決的,我們從列表中刪除 p,返回到 (A)(這是回溯)並嘗試第二種可能性,等等。最終我們將達到一個階段,除了一個列表之外,所有列表的長度都為 1。 如果最后一個列表的長度 > 0,則數獨是可解的。
這是一個簡化版本,它只是找到了一種可能的解決方案。 您必須自己編寫原型函數。
int getListLength(row, col); // number of possible values for this cell, 0...9
void checkConstrains(); // loop all sets (rows, columns, blocks)
// and find lists with one element. Remove
// this element from all other lists in the set.
// Repeat until no duplicates are found.
int *savelist(row, col); // make a copy of the list
void setlist(row, col, k); // set list of cell to { k }
getstate(), setstate(s); // save and set state of the game, ie. all lists
int solve( int row, int col ) {
int length = getListLength(row, col);
if(length == 0)
return 0; // unsolveable
// this is your recursion step slightly
// reordered to avoid row-overflow
if (col == 8 && row == 8) {
return 1;
}
int next_row, next_col;
if(col < 8) {
next_row = row;
next_col = col + 1;
} else {
next_row = row + 1;
next_col = 0;
}
if(length == 1) {
return solve(next_row, next_col);
}
// if we reach this step: length > 1
checkConstrains();
// length might have changed
length = getListLength(row, col);
if(length == 0)
return 0;
if(length == 1)
return solve(next_row, next_col);
// still: length > 1
// backtracking stage
int* list = savelist(row, col);
sudoku s = getstate();
for(int i = 0; i < length; i++) {
setstate(s);
setlist(row, col, list[i]);
if(solve(row, col))
return 1;
}
// all elements from list failed-->unsolveable
// free list and s
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.