一、项目介绍
首先附上项目的GitHub地址:https://github.com/Nevermore5421/PersonalProjectSudoku
拿到题目后,发现该项目的需求与数独有关,要求:
1)高效生成多个(1-1e6个)不重复的数独终局,并输出到文件。
2)高效解出多个(1-1e6个)有空缺的数独问题,并将结果输出到文件。
其中数独终局指的是一个9*9的盘面上每一行,每一列,每一宫(即3*3的小方形)中没有重复的数字。而解一个数独问题就是要从已经给好的数字中推测出一种可行的数独终局,得到一个可行解即可。
下面将展示我完成这个项目各项内容的思路描述以及制作过程。
1.PSP表格预估时间
PSP表格实际时间将在博文结尾处写出
PSP2.1 |
Personal Software Process Stages |
预估耗时(min) |
实际耗时(min) |
Planning |
计划 |
60 |
|
Estimate |
估计这个任务需要多少时间 |
2000 |
|
Development |
开发 |
1200 |
|
Analysis |
需求分析(包括学习新技术) |
480 |
|
Design Spec |
生成设计文档 |
60 |
|
Design Review |
设计复审(和同事审核设计文档) |
20 |
|
Coding Standard |
代码规范(为目前的开发制定合适的规范) |
20 |
|
Design |
具体设计 |
200 |
|
Coding |
具体编码 |
400 |
|
Code Review |
代码复审 |
60 |
|
Test |
测试(自我测试,修改代码,提交修改) |
200 |
|
Reporting |
报告 |
30 |
|
Test Report |
测试报告 |
20 |
|
Size Measurement |
计算工作量 |
10 |
|
Postmortem & Process Improvement Plan |
事后总结,并提出过程改进计划 |
60 |
|
|
合计 |
2000 |
|
2.解题思路描述
1)生成数独终局思路
拿到这道题后,我最先想到的思路就是暴搜,但是显而易见这样的效率极低,尤其是在应对1e6的数独终局的要求时。接着我便想到了对暴搜进行一定程度的优化,想到了如下两个思路:
- 用回溯法配合剪枝减少搜索层数和次数
- 用多线程进行优化,加快搜索速度
由于多线程此前我并未熟练使用过,故先用回溯法进行了小规模的数据试验,效率确实有所增加,但由于算法时间复杂度的限制,生成1e6的数独终局至少也要在1min以上的时间,这显然还远未达到期望值,故我对数独的特点进行了一定的观察,并从网络上查阅了一些资料后才有了我最终实现这个需求的思路:
一个完整的数独可以通过一个1-9的无重复的排列通过平移一定列数来生成。
意思就是例如698754321这个排列数,把他作为数独的第一行,我可以把下面的2-9行分别用第一行向右平移3,6,1,4,7,2,5,8列来得到一个完整的数独如下: