个人项目博客

1.github项目地址 
https://github.com/zhaobs-yu/sudoku


2.PSP表格

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

3.解题思路

拿到这个题目后,我想到的解题思路是首先解决解数独的部分,生成数独终局的时候就可以先随机生成数独残局,再利用解数独的方法把残局变为终局。 
解数独这个部分我的思路是先把可以确定唯一答案的空格填好,找不到这样的空格的时候,就找一个只有两个候选数的空格进行尝试。不断重复这两个过程,最终就可以把数独解出来。 
生成数独时我的方法是先往固定的几个格子里随机填写数字,形成一个数独残局,再用解数独的方法进行求解,生成数独终局。


4.设计实现过程

程序主要有以下这几个类。 

  • table包含一个数独表格的所有信息
  • block是一个格子的数据
  • row是一行的数据
  • column是一列的数据
  • area是一个九宫格的数据。 

程序主要有一下几个函数: 

  • fill函数:给某一格填上某数,并刷新当前数独表格与之相关的所有数据。 
  • work1函数 :把一个数独残局中可以确定唯一答案的空格填好。 
  • solve函数:解一个数独残局。 
  • make1函数:生成一个数独残局。 
  • makemany函数:生成n个数独终局。

5.程序性能

由于我的算法简单粗暴,所以我找不到可以改进性能的地方。 
下面是性能分析图

可见程序中消耗最大的函数是getcount,这个函数的作用是更新数独表格的候选数信息,每次填写一个数字以后都会调用getcount函数。


 

6.代码说明

 1 int solve(table *table1) {
 2     int point = 0;
 3     //printtable(table1);
 4     //printposs(table1);
 5     getcount(table1);
 6     //printcount(table1);
 7     int exit = 0;
 8     exit = work1(table1);
 9     //printtable(table1);
10     //printposs(table1);
11     //printcount(table1);
12     check(table1);
13     tabletry[point] = *table1;
14     point++;
15     tabletry[point] = *fill(table1, tryi, tryn[0]);
16     point--;
17     tabletry[point] = *fill(&tabletry[point], tryi, tryn[1]);
18     point++;
19     if (exit == 0) {
20         while (1) {
21             //cout << "begin try" << tryi / 9 + 1 << "行" << tryi % 9 + 1 << "\n";
22             error = work1(&tabletry[point]);
23             //printtable(&tabletry[point]);
24             //printposs(&tabletry[point]);
25             //printcount(&tabletry[point]);
26             if (error == -1) {
27                 //cout << "try another";
28                 point--;
29                 //cout << point << endl;
30                 if (point < 0) {
31                     //cout << "无解" << endl;
32                     return -1;
33                 }
34             }
35             else {
36                 if (check(&tabletry[point]) == 1) {
37                     //cout << "over" << endl;
38                     //printtable(&tabletry[point]);
39                     writetable(&tabletry[point]);
40                     break;
41                 }
42                 else {
43                     point++;
44                     tabletry[point] = tabletry[point - 1];
45                     point++;
46                     tabletry[point] = *fill(&tabletry[point - 2], tryi, tryn[0]);
47                     point--;
48                     tabletry[point] = *fill(&tabletry[point], tryi, tryn[1]);
49                     point++;
50                 }
51             }
52         }
53     }
54     else {
55         //cout << "无解" << endl;
56         return -1;
57     }
58     return 0;
59 }

solve函数先把数独表格中可以确定唯一答案的空格填好,找不到这样的空格的时候,就找一个只有两个候选数的空格进行尝试。不断重复这两个过程,直到解完数独或确定数独无解。 


 

7.总结

生成数独终局的部分我没有使用任何现有的高效算法,而是自己写了一个随机填数再求解的算法,算法的性能非常差,也不能保证生成的数独不会重复。

我自己测试的时候是生成10000个数独要12.5秒,更多的我也没敢试,我觉得生成1000000个大约要20分钟吧。

 

转载于:https://www.cnblogs.com/zhaobs/p/7598592.html

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐