• [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。

  • 相关阅读:
    低于时钟频率的任意频率生成(相位累加器)
    verilog实现奇数倍分频
    No.135 Candy
    No.42 Trapping Rain Water
    No.149 Max Point on a Line
    No.147 Insertion Sorted List
    No.21 Merge Two Sorted List
    No.88 Merge Sorted Array
    No.148 Sort List
    No.206 Reverse Linked List
  • 原文地址:https://www.cnblogs.com/Aria-K-Alethia/p/7593964.html
Copyright © 2020-2023  润新知