• 软件工程实践2017第二次作业


    ===================

    一、GitHub地址:https://github.com/xiaoknownothing/Fzuwork

    二、遇到的困难及解决方法

     一看到这个题目感觉可以选定一个空位,扫看所在行,所在列,所在宫,排除数字后选择数字填入,最好的情况所在行列的数字全部填满,这样就简单多了。可是这个数独棋盘只有一个数已知,其他的位子都有9个数要去“猜测”,每行每列每宫格子内数字还不重复,顿时脑子有点大,忙着搜索了一下,看了一些博客,才有了一些大概方向。
    

    三、解题思路

    用回溯法求解数独:

    • 1.从找第一个空的位子开始,找可选数(排除同行同列同宫重复的数),逐个放入
    • 2.找下一个空的位置,找可选数填入,如果这时候,发现此处空白格没有可选数,就回溯,换掉前面的可选数,再继续执行2
    • 3.直到空位子都满了就是一个数独解出来了
      //找出area[x][y]的可选数
    vector <int> find(int x, int y) 
    {
    	int a[10] = { 0 };
    	vector <int> ret;//声明一个int型向量ret 
    	for (int i = 0; i < 9; i++)
    	 {
    		if (sudu[i][y] > 0) 
    		a[sudu[i][y]] = 1;//所在行若有其他数,标记已使用 
    		if (sudu[x][i] > 0)
    	    a[sudu[x][i]] = 1; //所在列若有其他数,标记已使用 
    		
    	}
    	int row = x / 3, col = y / 3;//所在宫若有其他数,标记已使用 
    	for (int i = row * 3; i < row * 3 + 3; i++)
    	{ 
    		for (int j = col * 3; j < col * 3 + 3; j++)
    		 {
    			if (sudu[i][j] > 0) 
    			a[sudu[i][j]] = 1;
    		}
    	}
    	for (int i = 1; i <= 9; i++) 
    	{
    	if (!a[i]) ret.push_back(i);//逐个填入剩余可选数 
        }
    	return ret;
    }
    
    void update() {
    	for (int i = 0; i < 81; i++) area[i].clear();
    	chosen = make_pair(0, 10);
    	can_update = false;
    	for (int i = 0; i < 9; i++	)
    	{
    		for (int j = 0; j < 9; j++) if (sudu[i][j]==0) 
    		{
    			int k = i * 9 + j;//k为该空白格序号 
    			area[k] = find(i, j);//填入可选数 
    			if (area[k].empty()) is_blank = false;//没有可选数 
    			if (area[k].size() < chosen.second) chosen = make_pair(k, area[k].size());//更新 
    			can_update = true;
    		}
    	}
    }
    
    void num_sudu() 
    {
    	update();
    	if (can_update==false)
    	 {
    		num++;
    		if (num >=N) is_over = true;
    		print();
    	}
    	else if (is_blank==false) 
    	{
    		return;
    	}
    	else if (is_over==false)
    	 {
    		int areaition = chosen.first;
    		int x = areaition / 9;
    		int y = areaition - x * 9;//x,y为该位置坐标 
            int size = chosen.second;//size为选中数个数 
    		vector <int> k = area[areaition];
    		for (int i = 0; i < size; i++) 
    		{
    			sudu[x][y] = k[i];
    			num_sudu();
    			sudu[x][y] = 0;
    			is_blank = true;
    			// 回溯, 还原数据, 原is_blank, 前面的深搜,都没有正确答案,会导致is_blank=false
    		}
    	}
    }
    

    四、测试

    • 运行测试

    五、PSP

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

  • 相关阅读:
    【转载】Sqlserver存储过程中使用Select和Set给变量赋值
    【转载】腾讯云如何将一个域名解析到另一个域名上
    【转载】Sqlserver限制最大可使用内存
    【转载】 腾讯云通过设置安全组禁止某些IP访问你的服务器
    【转载】 C#使用Select方法快速获取List集合集合中某个属性的所有值集合
    【转载】哪些域名后缀可在工信部进行备案操作
    【转载】 C#使用string.Join快速用特定字符串串联起数组
    【转载】Sqlserver使用Convert函数进行数据类型转换
    【转载】Sqlserver根据生日计算年龄
    【转载】 腾讯云硬盘不够用,如何对硬盘进行扩容
  • 原文地址:https://www.cnblogs.com/xiao2017/p/7502581.html
Copyright © 2020-2023  润新知