public static int[][] solve(int[][] input){
for (int i = 0; i < 9*9; i++){
if(input[i/9][i % 9] != 0){
continue;
}
for (int j = 1; j <= 9; j++){
if(validNumber(input, i/9, i % 9, j)){
input[i/9][i % 9] = j;
solve(input);
}
}
}
return input;
}
該方法應通過回溯解決(可解決的)數獨難題,無論初始情況如何。它的工作原理是這樣的:通過回溯解決數獨(java)
給定一個數獨謎題,它將從每一行的左上角迭代到二維數組的右下角。當已經有一個號碼時,它會被跳過。當存在零(空場)時,它通過validNumber
方法計算可能的值。第一個有效數字(從1到9)放在該字段中,方法進入下一個字段。
在這個算法中,該方法現在不會生成一個有效的數字是否最終會使難題無法解決。
我想改變它像這樣:
在結束時,當該方法結束通過整個2D陣列迭代,如果是零或不陣列的每個條目被測試。
如果甚至有一個零,則整個算法必須到達第一個「有效」號碼所在的位置。現在,下一個「有效」號碼被放入,直到沒有零點算法的結尾。
我有一些麻煩實施這個想法。在我看來,在某個地方必須有另一個for循環,或者類似goto
聲明,但我不知道該把它放在哪裏。
有什麼建議嗎?
該策略需要一套全面的規則來消除數字。一些「硬」水平的數獨謎題需要複雜的規則,基本上模仿嘗試和檢查的方法,而不用實際嘗試不同的組合。我很好奇,如果你的求職者可以處理空謎作爲輸入。看到我的答案基於樹的遞歸。我甚至用它來解決空白拼圖問題,它在合理的有限時間(秒)內爲我提供了正確的解決方案。 – Andrey
@Andrey - 不,我的解決方案無法處理空板。它基於「消除過程」。由於沒有任何可以消除的東西,所以它會停下來。我的解決方案使用了6或7種不同的淘汰技術。唯一的嘗試和檢查方法是,當董事會留下只有3個空曠的廣場,並沒有其他消除技術可以解決它。源代碼不是立即可用的(磁盤處於脫機狀態),否則我會發布它。 – selbie
@selbie你是如何處理回溯?使用遞歸時,堆棧將跟蹤移動歷史,因此您通過返回到前一個堆棧框架來回溯。像你提到的迭代解決方案更適合稱爲「暴力」,而不是OP所嘗試的。回溯不是蠻力。他只是沒有做好回溯部分。我很想知道你的代碼如何在現代臺式機CPU上處理一個「硬」電路板(如我的代碼答案中的文章)。我的代碼在我的機器上需要大約75ms。沒有回溯,我認爲這是不可能解決的。 – The111