zoukankan      html  css  js  c++  java
  • 软件工程实践2017第二次作业-数独生成器

    github : sudoku

    一. 问题描述

    • 阅读《构建之法》第一章至第三章的内容。
    • 随机生成n个不重复且已解答完毕的数独棋盘。

      数独盘面是个九宫,每一宫又分为九个小格,在每个空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次。

    • 数独左上角第一个数为 : (学号后两位相加)%9+1。
    • 输出到sudoku.txt。

    二. 问题分析与思考

    1. 数独每个格子的数字 num 的性质
      • 该行其他格子不出现 num。
      • 该列其他格子不出现 num。
      • 该宫其他格子不出现 num。

    2. 如何快速判断数字x满足上述条件可填入(r, c)格子?
      • 循环行、列、宫判断? 太慢了.
      • 牺牲部分空间,对行、列、宫已经出现的数字进行mark,便可快速判断了。

    3. 枚举数进行填充:
      • 从1到9遍历枚举. (生成的数独看着一点随机性都没有)。
      • 随机生成一个数,[1,9]之间, 以这个数为起点去枚举.(增加了数独随机性, 似乎速度上也加快了一点)。

    4. 预处理:
      • (r,c)对应的宫数 = ((r % 3) ? r : (r - 1)) / 3 * 3 + ((c % 3) ? c : (c - 1)) / 3 + 1;求优雅的计算方式。
      • (1, 1) = (学号后两位相加)%9+1。
      • 特殊输入处理。

    5. 输出优化
      • 使用putchar( )优化输出。

    三. 代码设计流程图

    流程图

    四. 代码编写

    void sudoku::dfs(int x, int y)
    {
    	if (flag) return;//已经输出n个则退出搜索
    	int i, j;
    	if (x == 9 && y == 9) {
    		++cnt;
    		out();//输出数独矩阵
    		if (cnt != target)  putchar('
    ');
    		if (cnt == target) {
    			//getchar();
    			flag = true;
    		}
    		return;
    	}
    	
    	//填写下一格的数 
    	int nx = x, ny = y + 1;
    	if (ny == 10) ny = 1, ++nx;  //  跳到下一行 
    	int now = getgg[nx][ny];	// 第x宫 
    
    	//此处由循环1-9 改成 随机生成数再进行循环  => 增加数独的随机性
    	int cur = rand() % 9 + 1; 
    	for (i = cur; ; ) {
    		// 满足该行or该列or该宫不重复
    		if (!row[nx][i] && !cow[ny][i] && !gg[now][i]) {
    			row[nx][i] = true, cow[ny][i] = true, gg[now][i] = true, vec[nx][ny] = i + '0';
    			dfs(nx, ny);
    			row[nx][i] = false, cow[ny][i] = false, gg[now][i] = false, vec[nx][ny] = '0';
    		}
    		++i;
    		if (i>9) i = 1;
    		if (i == cur) break;
    	}
    	return;
    }
    

    五. 性能分析

    • 测试数据: 100w = 1e6

    • CPU使用率报告

      • 主要耗时在于dfs.
      • let us go to dfs() ↓

    • dfs 函数分析报告

      • 上图显示, 输出数独矩阵的函数out()与枚举数占用的比例最大.
    • 根据分析报告优化

    • 输出部分由putchar()替换printf(), 输出明显加速
    • 枚举起点采用随机数, 使得枚举的数尽可能早地满足条件
    • 还存在一定的优化问题, 有待补充.

    六.输出结果

    七.单元测试及代码覆盖率

    有待完成...

    八. PSP

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

    九. 补充

    1. 关于putchar比printf快? 2017.9.14
      • putchar, 单字符输出,无格式控制, 速度快
      • printf 格式化输出, 比putchar慢.
  • 相关阅读:
    MongoDB遇到的疑似数据丢失的问题。不要用InsertMany!
    MongoDB-Java的两个基本操作Upsert和insertMany
    MongoDB With Spark遇到的2个错误,不能初始化和sample重复的key
    mongoDB启动前的系统设置,解决部分Warning问题
    使用commons-compress解压GBK格式winzip文件到UTF8,以及错误使用ZipArchiveInputStream读出来数据全是空的解决办法
    mongodb查看操作记录方法以及用户添加删除权限修改密码
    java及spark2.X连接mongodb3.X单机或集群的方法(带认证及不带认证)
    MongoDB3.X单机及shading cluster集群的权限管理(基于3.4.5)
    element ui form表单清空规则
    input type file上传文件之后清空内容。
  • 原文地址:https://www.cnblogs.com/winforbest/p/7500564.html
Copyright © 2011-2022 走看看