個人作業 數獨

2022-08-21 23:39:12 字數 3322 閱讀 6711

ps:名字好像起錯了》 <

psp2.1

personal software process stages

預估耗時(分鐘)

實際耗時(分鐘)

planning

計畫10

12· estimate

· 估計這個任務需要多少時間

1012

development

開發1610

2350

· analysis

· 需求分析 (包括學習新技術)

4030

· design spec

· 生成設計文件

2025

· design review

· 設計複審 (和同事審核設計文件)105

· coding standard

· **規範 (為目前的開發制定合適的規範)

2010

· design

· 具體設計

2060

· coding

· 具體編碼

1440

2100

· code review

· **複審

3060

· test

· 測試(自我測試,修改**,提交修改)

30120

reporting

報告95

115· test report

· 測試報告

3050

· size measurement

· 計算工作量55

· postmortem & process improvement plan

· 事後總結, 並提出過程改進計畫

6060

合計1715

2477

有很大一部分時間花在調bug上了(捂臉)。一開始沒有仔細記錄好各個引數的具體含義和範圍,過一段時間修改時憑記憶去改那些引數,超容易產生各種小bug。

先說說等價數獨。乙個數獨終局通過各類變換可以生成超大量的等價數獨。但是,由於題目中提到了不重複原則,假使要求生成的數獨數量大於乙個等價數獨組,那麼查重部分就會消耗大量的時間,反而得不償失。也沒有找到乙個能識別不同等價數獨的特徵。便放棄了這個想法。

不考慮等價數獨,數獨的生成和求解,在本質上都可歸為求解數獨的過程,只不過生成相對於全0的數獨求解,且不會因得出乙個解答停止。

第乙個想到的方法,大約也是最簡單粗暴的方法,就是無腦遞迴遍歷,輸出可行解。通過每次檢查插入是否可行來決定往下一層or繼續嘗試,但同時想到,檢查插入的可行性本身是乙個極佔執行比重的部分,即使可以一次計算出乙個遞迴過程中的所有可填入值,單純通過數獨局來遍歷仍會占去大量執行時間。於是開始考慮如何儲存每次遞迴過程衝突資訊,以快速檢查插入的可行性。

由於也是乙個回溯演算法,加之判斷衝突,便聯想到了n皇后問題。在查詢資料的過程中,這篇部落格給了我很大啟發。通過劃分衝突種類,以0|1方式表示衝突與否,很大程度上減少了建立、回溯衝突表本身,以及衝突表使用所花費的時間。同時這個方法特別適合在一次填完乙個數字的回溯方法中使用。這也就是我之後程式的基本思路。

最終的設計思路:一次填完乙個數字,每個數字按第一行往第九行的順序填入,衝突表有三個:列衝突表[每個數字],九宮格衝突表[每個數字],整體的數獨衝突表

建立乙個suduku類,提供生成、解數獨方法。

sudu_solve 解答的入口方法

sudu_to_file 數獨寫入檔案

單元測試

有很多是private方法,難以從外部呼叫。測試函式採用呼叫入口函式,檢查數獨終局的正確性的方式來進行測試。另有命令列輸入的數字的合法性的檢測。

生成部分的**寫完後,迫不及待的試了一試——1s、10s、100s...當我終於忍不下去了強制結束程式時,不過輸出了20w個數獨。問題很快就發現了:檔案io。當時採用的是乙個數字乙個數字輸出到檔案的方式,極其拖慢性能。之後我為其申請了乙個輸出到檔案的buf,每次呼叫sudu_to_file時先將輸出暫存在buf中,等buf快滿了,一次性輸出到檔案。在程式結束前再調一次sudu_to_file_flush來將還在buf中的資料輸出到檔案。

接下來做了一些小優化。刪去了**中的一些多餘的計算等。

可以發現函式消耗的比例很相似,因為解答時基本使用的是同乙個演算法。

void sudu_gene_loop(int order, int & now_num, int target_num) 

else

//更新衝突表

sudu_insert_0(i, num, depth, order_num);

sudu_gene_loop(order + 1, now_num, target_num);

if (now_num == target_num) return;

sudu_delete_0(i, num, depth, order_num);}}

} }

回溯中判斷可行操作的關鍵**(即衝突表的使用):

canset = gene_row[num] | gene_hasput[depth] | gene_33[order_num * 9 + depth / 3];

for (int i1 = 1; i1 < 10; i1++)

else if (i <= 5)

else if (i <= 8)

} else if (depth < 6)

else if (i <= 5)

else if (i <= 8)

} else if (depth < 8)

else if (i <= 5)

else if (i <= 8)

} }

衝突表的回退:

插入的逆過程

void sudu_delete_0(int i, int num, int depth, int order_num) 

else if (i <= 5)

else if (i <= 8)

} else if (depth < 6)

else if (i <= 5)

else if (i <= 8)

} else if (depth < 9)

else if (i <= 5)

else if (i <= 8)

} sudu[depth * 9 + i] = 0;

}

數獨、衝突表的初始化:

void sudu_solve_init() 

}} }

個人專案數獨

2 每一行都要有1 9這9個數字填入 3 每一列都要有1 9這9個數字填入 4 每一塊都要有1 9這9個數字填入。所以,01模型中列的定義就出來了。i,j,k表示在棋盤上i行j列填入數字k。1到81,表示棋盤中9 9 81個格仔是否填入了數字。如果是,則選取的01行在該01列上有1。對應的01列編號...

個人專案 數獨

個人專案 數獨 再附psp表乙份 personal software process stages 估計耗時 分鐘 實際耗時 分鐘 計畫30 40需求分析 包括學習新技術 00 生成設計文件00 設計複審00 規範00 具體設計 300360 具體編碼 600530 複審 5030 測試200 23...

個人專案 數獨遊戲

數獨 二 生成數獨終局 數獨 三 解數獨 數獨 四 測試與效能分析 數獨 五 總結 數獨 六 ui介面 下面是我預計在專案上花費的時間。psppersonal software process stages 預估耗時 分鐘 實際耗時 分鐘 planning 計畫25 estimate 估計任務用時 ...