1. 程式人生 > >【數獨個人專案】2. 拿到題目之後

【數獨個人專案】2. 拿到題目之後

github地址:https://github.com/Duuang/Project-Sudoku

日期:2018-12-15

2. 拿到題目之後

    這個就是相當於自己做一個專案嘛,體驗專案的全套開發過程。

    於是我打算,一定不能上來就啪啪啪寫程式碼,要遵循軟體工程規範從頭到尾體驗一次,肯定會有不少收穫,也能為之後真正做專案打下基礎。

    於是:先要決定大概的軟體開發流程,我選擇的迭代的開發模型,流程大概是:

    可行性分析與計劃->需求分析->設計->實現->測試->提交,並反覆迭代

 

一、可行性分析與計劃:

1. 可行性分析:(肯定可行。。)

2. 計劃: 已經在上篇部落格中給出,用PSP 2.1表格做出了計劃

二、需求分析:

       從pdf文件中獲取,專案中的需求還是寫的很清楚的,分為:①生成數獨  ②求解數獨

解題思路:

1. 生成數獨:

        可以理解為,就是要生成100萬個不重複的數獨(左上角數字固定),然後儲存在檔案裡,關鍵還有個時間限制,60秒內要能生成1000個,並且速度越快越好。

        先不考慮效能需求,生成100萬個重複數獨。我去查了一下,不同的數獨大概一共有6.671*10^21種。。感覺生成100萬個不是小意思嘛?用最暴力演算法的話,相當於從左上角,一個格子一個格子的從1到9生成,如果不滿足條件就回溯,繼續查詢,就相當於不剪枝的回溯法,直接列舉,這樣甚至都能夠把所有可能解按照dfs順序都枚舉出來。

       但是。。。估計了一下,可能太慢了,剪枝的話目測也提升不了太多速度。關鍵是。。只要生成6.671*10^21中的100萬個就行,從頭挨個列舉有點蠢。。

        後來搜尋數獨生成演算法,看到了一些高階演算法,感覺還是有點扯大了。再後來在一篇部落格中看到了9!這個數,有362880這麼大。。那豈不是隻要構造出來仨數獨,然後1到9全排列一下,按不同順序塞進去,不就完事了?(然後直接怒敲了仨9×9的陣列上去)後來發現左上角固定。。 8!是40320,也就是說需要25個數獨,8個數全排列。所以就轉為考慮,能不能生成出來25個不同數獨?(不能經過全排列之後相同)

       後來發現能,第一排不妨假設就是1到9,那把第二行的456和789,兩個都全排列下,就有了6*6=36種基本數獨,問題解決!

        所以就是先生成25個基礎數獨,再按8!全排列下,就有了100萬個

        當然還有兩個問題就是讀控制檯引數並做錯誤處理,和將數獨按格式寫入檔案,不過這兩個都簡單,不涉及到演算法

2. 求解數獨

        看了下,沒有效能要求!所以只考慮可接受時間內可解即可。而且不是要枚舉出全部解,是隻要一個解即可。

        那就簡單了,因為數獨題裡空多的話,列舉的可能性少,好填;數獨題裡空少的話,約束也少,也很容易就能枚舉出一個合格解。所以其實直接回溯列舉+剪枝即可。(甚至剪枝都不必要)如果追求好點的解法,優先選可能性少的、啟發式資訊有利的空格來進行節點擴充套件,肯定速度能提升很多。當然還有很多高階演算法,不過好多演算法都是為了求數獨的完全解的,沒必要。

        所以最後決定就是回溯+剪枝,有機會的話會嘗試更好一些的演算法。

三、階段總結和收穫:

      正式開始正規的軟工專案流程了!拿到題目後做了計劃,先通過讀pdf,分析了需求,然後通過查閱資料、自己思考,有了一個大概的解題思路。至此,可行性分析與計劃、需求分析階段結束。

      收穫就是,體會到了需求對專案思路的重要性。。要是這個需求是生成哪怕再多兩個數量級的數獨,那這個方法恐怕都已經不奏效了。。因為這個輸入最大隻有100萬,於是可以方便的用更快速更簡單的演算法來達到需求。(畢竟達到需求就可以交付了嘛,比如用了個能生成全部數獨的演算法,但是人家輸入就100萬,那超出100萬的部分其實就是沒用處的..)