編寫乙個程式,通過已填充的空格來解決數獨問題。
乙個數獨的解法需遵循如下規則:
數字 1-9 在每一行只能出現一次。
數字 1-9 在每一列只能出現一次。
數字 1-9 在每乙個以粗實線分隔的 3x3 宮內只能出現一次。
空白格用 『.』 表示。
示例:
note:乙個數獨。
答案被標成紅色。
給定的數獨序列只包含數字 1-9 和字元 『.』 。
你可以假設給定的數獨只有唯一解。
給定數獨永遠是 9x9 形式的。
方法一:列舉法。
對於每個格仔,可以填入 1 ~ 9 個數字,共有 9 * 9 個格仔,因此一共有 9^ 種組合方法。
將上述組合方法列舉出來,選擇滿足條件的乙個即可。
上述方法雖然理論上可行,但執行時間太大,現實中不可能使用該方法。
方法二:dfs + 回溯
我們將 9 個「宮」按照以下標記劃分:
首先遍歷陣列,記錄每組/每行/每宮中已經出現的數字,並據此求出每行/每列/每宮中可以放置的數字,將其存入雜湊表中。
例如:
第一行還能放置的數字有:1,2,4,6,8,9;
第三列還能放置的數字有:1,2,3,4,5,6,7,8,9;
第一宮還能放置的數字有:1,2,4,7.
隨後開始 dfs, 對於每乙個沒有放置數字的格仔,依次檢查是否可以放置數字 1~9, 若可以放置,則放置該數字,並在對應的雜湊表中刪去該數字。若不能放置,則證明需要回溯。
例如:在上例中,對於位置 [0,3], 依照雜湊表,我們可以將 1,2,4 三個數字放入其中。
什麼時候需要回溯?
例如:
在 [0,8] 位置上, 已經無元素可放(元素 『6』 不能放在這裡,因為第 8 列/ 第 6 塊 已經存在元素 『6』),此時需要回溯。這時證明之前的放置序列並不正確,我們在此時 return 出當前函式(即返回上一層遞迴中)。
即返回到 [0,7] 位置處,對於 1 ~ 9, 已經遍歷到 『9』, 因此此處也不能放置除 『9』 以外的數字,再返回上一層。
在 [0,6] 位置處,可以放置 『8』 和 『9』, 由於 『8』 已經證明不可行,因此嘗試放置 『9』.
以上過程即回溯。
**:
class
solution
;//a 行;b 列;c 宮
for(
int i =
0; i <
9; i++
) line.
push_back
( compare)
, column.
push_back
( compare)
, block.
push_back
( compare)
;for
(int i =
0; i <
9; i++
)for
(int j =
0; j <
9; j++)if
( board[i]
[j]!=
'.')
return;}
//檢查該位置處字元是否可以放到該處
bool
check
( vector
char
>>
& board,
const
int& i,
const
int& j,
int num)
//標記
int flag =0;
//dfs + 回溯
void
dfs( vector
char
>>
& board,
int count)
int i = count /
9, j = count %9;
if( board[i]
[j]==
'.')
else
return;}
}else
dfs( board, count +1)
;return;}
void
solvesudoku
(vector
char
>>
& board)
};
**拆開看有點長且繁瑣,若把函式拿出來單獨看:
這樣就好多了(自我感覺寫的很好看,不接受反駁/批評)
數獨問題 解數獨
數獨是乙個非常有名的遊戲。整個是乙個9x9的大宮格,其中又被劃分成9個3x3的小宮格。要求在每個小格中放入1 9中的某個數字。要求是 每行 每列 每個小宮格中數字不能重複。現要求用計算機求解數獨。輸入描述 輸入9行,每行為空格隔開的9個數字,為0的地方就是需要填充的數字。輸出描述 輸出九行,每行九個...
題解 數獨 養生題
優雅的暴力 搜尋演算法小結 不過我還用了隨機化搜尋,這種搜尋思想可以防止被毒瘤出題人卡掉。有興趣的可以看一下我的一篇總結裡面寫了搜尋的一些技巧。對於實現,我的思路是.不好說,但是這樣寫搜尋又快又穩還短。以上是洛谷裝逼的話 winlere include include using namespace...
構造解數獨
public class sudoku 尋找橫座標下一位置 int findx int x,int y 尋找縱座標下一位置 int findy int x,int y 輸出完成的數獨矩陣 void sdprint system.out.print n system.out.print n 判斷當前位...