[buaa-SE-2017]个人项目

个人项目


Part1:github

https://github.com/Aria-K-Alethia/Sudoku


Part2:解题思路描述

关于数独的解法

我选择的是暴力搜索算法。

(1)关于 -c
首先,本题要求生成的数独最多为1,000,000个,并且要生成的数独都是9x9规模的,而并不是nxn规模,再加上数独本身的限制可以实现一定程度上的剪枝,因此暴力搜索是可行的。

另一方面,本题需要生成的数独各不相同,暴力搜索可以搜索所有的可行解,很容易实现不重复的要求,所以最终我选择暴力搜索的方法。

(2)关于-s
暴力搜索在解决数独的时候只需要搜索到一个解就可以,虽然对于一些递归层数比较深的数独会有些乏力,不过总体上也可以接受。

关于其他解法

我在分析的题目时候查找了其他的解法,包括dancing link、分治,但是dancing link的复杂度较高(参看算法实践——舞蹈链(Dancing Links)算法求解数独),且其实现复杂,所以不使用。

分治的方法将9x9盘面分成9个3x3的盘面,每次在每个盘面上生成数字,这个和普通的回溯法实际是类似的,所以效率应该也类似(关于效率参看【算法研究】数独高效完全解生成算法的研究和实现),而且最后我用暴力法实现之后也证明了这一点。


Part3:设计实现过程

关于设计

我的设计比较简单,整个程序分为3个类:

  • InputHandler:处理和分析输入。
  • Sudoku:处理所有数独相关操作。
  • Output:处理所有错误输出。

程序的流程就是由InputHandler处理输入,然后Sudoku根据不同的指令来解决,如果这个过程中有什么错误发生则会由Output响应。

关于测试

测试中,首先测试了基本功能,然后针对一些边界值(比如空文件和生成0个数独)进行了测试。
在性能改进之后,又进行了回归测试。
测试初始化:

这里设置了相关参数

下图是其中一个测试单元:

这个测试单元测试了

bool get_board(fstream &file,char board[][LEN+1])

这个方法从file文件中读入一个数独,成功则返回true,如果数独的行数不够则返回false,我们首先读入一个正确的数独,然后在文件中输入错误信息之后重新测试,这时outcome变量应该是false。


Part4:性能分析和改进

我在性能改进上大概花费了3个小时的时间。
最初我使用了c++的内置类string来处理输出,但是性能分析之后发现速度太慢,输出1million个需要1分钟,所以我针对这一点以及I/O输出进行了优化,具体体现在:

  • 替换string转而使用char*来处理字符串
  • 将所有结果存储在一个大数组中,最后直接输出所有结果,而不是每次输出一个数独终局。

之后程序在I/O上已经不花费太多的时间,根据性能分析图可以看到,大部分的时间都集中在回溯搜索上:


Part5:关键代码

回溯部分代码:

for (int k = 1; k <= LEN; ++k) {
        if (Sudoku::count >= n) return;    //if generate enough sudoku,return
        if (check_generate_pos(i, j, k)) {   //check if it is ok to set k on (i,j)
            board[i][j] = k + '0';
            trace_back_n(i, j + 1, n, file);    //if can,recur to next place
        }
}

遍历所有可能的数字,首先检查生成的数独是否足够,如果足够就返回,不足够就检查当前数字能否插入位置(i,j),如果能就插入然后继续递归。


Part6:PSP表

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 20
· Estimate · 估计这个任务需要多少时间 5 5
Development 开发 60 60
· Analysis · 需求分析 (包括学习新技术) 180 480
· Design Spec · 生成设计文档 30 20
· Design Review · 设计复审 (和同事审核设计文档) 0 0
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 5 0
· Design · 具体设计 60 120
· Coding · 具体编码 120 180
· Code Review · 代码复审 60 180
· Test · 测试(自我测试,修改代码,提交修改) 60 60
Reporting 报告 30 30
· Test Report · 测试报告 30 30
· Size Measurement · 计算工作量 5 5
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 30 30
Total 合计 705 1220

Part7:总结

由于我之前没有学过C++,所以这次在技术学习上花费了很多时间,导致最后没有太多的时间来coding,所以个人觉得这次代码的质量并不太好。
不过这次也有很多收获,能初步运用C++、学了VS这个超强大IDE。

posted @ 2017-09-25 21:03 Alethia 阅读(...) 评论(...) 编辑 收藏