软工实践第二次作业

Github:https://github.com/031502216/softWare

作业地址:http://www.cnblogs.com/easteast/p/7469291.html

PSP 2.1表格

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

 

学习进度条:

时间    

新增代码(行)                                        

本周学习耗时(小时)                                                          

累计学习耗时(小时)                                                                   

重要成长

2017.9.3-2017-9.10                                                                

200 20 20 对回溯法有了更深的认识,C++挺久没有接触了,这一次写的有些吃力,还有一些以前没有接触过的工具要一步步调试,觉得挺有收获,不过看着自己和有些人在编程这方面确实存在很大差距,所以接下来要加把劲了。
...        

 

解题思路:

由于许久没有写过c++,所以感觉很多之前学的知识都已经没有什么印象,只能一点点回忆,慢慢完成本次作业,。在拿到题目后,自己先动手解了一下数独,发现解是可以解出来,但是没有找到特别的好技巧,只能慢慢推理。然后查询了一些专门的解数独教程,方法也是多种多样,但是能够提供解决问题算法的没有太多,后来参考部分的网上资料,大致提供了两种解决方法,分别是回溯和置换。置换法对于本题不太合适,那就使用回溯法。从问题的某一种状态(初始状态)出发,搜索从这种状态出发所能达到的所有“状态”,当一条路走到“尽头”的时候(不能再前进),再后退一步或若干步,从另一种可能“状态”出发,继续搜索,直到所有的“路径”(状态)都试探过。这种不断“前进”、不断“回溯”寻找解的方法,就称作“回溯法”。但是在回溯的过程中怎么样才能将所有符合条件的数独全部输出呢?数独一般都是提供几个数字,然后根据规则填入相应的格子,但是本题是固定了左上角的数字,然后输出满足条件的数独,并非解数独那种单一的解法结构。但是相同的是需要用同一种规则去判断,生成的结果是一个81格的数独。

实现的时候有几个问题:

1.不能生成相同的数独,那么在生成第一个数独以后怎么把第二个数独输出?

2.一个个的按顺序往格子里填写数字,是不是对于性能方面有许多限制,浪费很多时间。

3.看到一些人在使用的时候使用了rand()这种随机函数,这种方法是否对于生成数独性能上和唯一性上有较大的提升?

综合这些问题,再去寻找答案,心里对于回溯这个方法还是比较认可,也是一个效率相对较高的方法。

设计实现:

代码中有两个函数,back()回溯函数和Isvaild()判断放置数字是否合法。

工作流程图:

代码说明:

bool Isvaild(int  count)  //判断是否合法
{
    int row = count / 9;  
    int col = count % 9;  
    int j;  
    //同一行  
    for(j = 0; j < 9; ++j){  
        if(map[row][j] == map[row][col] && j != col){  
            return false;  
        }  
    }  
    //同一列  
    for(j = 0; j < 9; ++j){  
        if(map[j][col] == map[row][col] && j != row){  
            return false;  
        }  
    }  
    //九宫格  
    int Row = row / 3 * 3;  
    int Col = col / 3 * 3;  
    for(j = Row; j < Row + 3;++j){  
        for(int k = Col; k < Col + 3; ++k){  
            if(map[j][k] == map[row][col] && j != row && k != col){  
                return false;  
            }  
        }  
    }  
    return true;  
}
void back(int k,int request){   //进行回溯
    while(1)  
    {  
        int i = k/9;  
        int j = k%9;  
  
        while(1)  
        {  
            map[i][j]++;  
            if(map[i][j] == 10)  
            {  
                map[i][j] = 0;  
                --k;  
                break;  
            }  
            else if(Isvaild(k))  
            {  
                ++k;  
                break;  
            }  
        }  
        if(k == 81)  
        {  
            for(int i = 0; i < 9; ++i){  
                for(int j =  0; j < 9; ++j){  
                    fout<<map[i][j]<<" ";  
                    //cout<<map[i][j]<<" ";  
                }  
                fout<<endl;  
                //cout<<endl; 
            } 
            num++;
            fout<<endl;
            //cout<<endl;
            if(num >= request)  
                return;  
  
            --k;  
        }
        
    } 

测试运行:

 测试运行:

n=1000时

由上述截图可以看出back()回溯函数占用了75%的时间,所占用的比例较重。

在本次作业实现过程中,我是发觉了自己的程序其实是有很大的优化空间的,但是由于时间和能力限制,并没有去实现,但是接下来会去尝试。以下提供一个解决问题的更好的思路可以减少回溯的次数例如dfs深度优先算法还有一个博客推荐的算法跳转链接也可以尝试,都比目前的方法更加优化。在本次的作业中,确实发现自身有很多不足的地方,包括对学术钻研的心态和能力,这是以后要努力的地方。

原文地址:https://www.cnblogs.com/forfly/p/7501038.html