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慢.
  • 相关阅读:
    hdu 5119 Happy Matt Friends
    hdu 5128 The E-pang Palace
    hdu 5131 Song Jiang's rank list
    hdu 5135 Little Zu Chongzhi's Triangles
    hdu 5137 How Many Maos Does the Guanxi Worth
    hdu 5122 K.Bro Sorting
    Human Gene Functions
    Palindrome(最长公共子序列)
    A Simple problem
    Alignment ( 最长上升(下降)子序列 )
  • 原文地址:https://www.cnblogs.com/winforbest/p/7500564.html
Copyright © 2011-2022 走看看