1. 程式人生 > >1426. Sudoku Killer(HDU)

1426. Sudoku Killer(HDU)

題意理解

數獨問題: 9×9數獨,實現自動填數。輸入格式要求是空行相隔,輸出格式也是空行相隔,(其他條件理解簡單就不重複)

問題分析

用dfs搜尋

數獨玩過,大致規則就是一個dfs搜尋,每個空位有多個可選值,確定值後填下一個空位,如果下個空位無值可填,就回滾到上一個空位,填成新的值,直到所有值都填成功。

確定搜尋空間為空位,以整個數獨為空間非常大不合適,用vector,元素為橫縱座標的結構體。

確定驗證空位值條件,要求橫行、豎行數字不重複,小範圍(9×9分為3×3個小範圍)內數字不重複,橫豎行容易,遍歷9個位置,如果和填值一樣就無效;小範圍計算左上角點(i/3*3),然後加3的步長即可。

非遞迴遍歷演算法思路,遍歷空位點序列,對於當前空位點,校驗1-9中有效值,放入棧中,如果有有效值,彈棧,填充當前空位,否則,執行回滾,彈棧,如果當前空位比棧頂元素序號大1,直接修改數獨棧頂元素序號空位值;否則,當前空位比棧頂元素序號大很多,迴圈清空棧頂元素序號數獨的空位值,再彈棧,直到修改數獨棧頂元素序號空位值結束。

對於輸入的處理,此題輸入是一個矩陣,方法是迴圈輸入字元,設定行列座標i和j,如果字元是1到9,設定a[i][j]的值為字元-'0';如果字元是?,設定a[i][j]為0,並放到搜尋空間vector中。如果j為9,就表示一行輸入完成換行;如果i為9,就表示矩陣輸入完成,進行dfs搜尋,為了支援多個矩陣處理,需要重置i,j為0。

對於輸出的處理,輸出是在輸入的i為9中來處理,當矩陣輸入完成,第一次輸出前不需要加空行,第二次就需要加空行,否則失敗。

其他

深度遍歷搜尋不一定是在樹結構,也不一定是在圖結構,也不一定要在類似於圖或樹的結構上處理,只要設定搜尋空間,搜尋結果驗證方法,搜尋終止條件等就可以用深度遍歷。

非遞迴和遞迴考慮的不同,遞迴簡單一些,非遞迴可以看出把遞迴的棧手動來實現了。

 

對於複雜程式除錯,因為輸入複雜,輸出也複雜,控制檯除錯不夠用了,需要新的方法處理

freopen("1.txt", "r", stdin); freopen("2.txt", "w", stdout); 用完註釋掉就可以了,這是好東西。!

一共19次,從2018-11-07 13:26:20 到 2019-01-02 15:18:17 歷時 56天 1時 51分 57秒,這是我做過的最長時間的一道題。

前後做了半年了,一直超時,如果這題我一直超時,那麼我的演算法之路就到此為止。我會做題,直到ac。期間不會再刷其他的題。

2019/1/2 終於ac了,問題是計算輸出是,第一次輸出數獨結果不需要前置空行,後面處理每次需要前置空行。我的錯誤是第一次輸出數獨結果也加空行了。也就是說我的非遞迴演算法和遞迴演算法也是可以的。一直超時的原因是,如果遍歷演算法不對,那麼會在搜尋空間來回遊走,退不出來,如果輸出需要空行間隔,他會等待空行。

2019/1/1 題例可以解決,但是換了一個例子就超時,檢查發現設計的演算法會很久,反覆修改空位值

2018/12/30 重新設計dfs演算法,這次考慮從空位入手,將空位當成搜尋物件處理。樣例可以解決,但是跑超時

2018/10 按照棋盤為搜尋物件,dfs搜尋發現超時,更新校驗方法,無效。

連結

https://github.com/xierensong/learngit/tree/master/hdu/1426