2017.9.9 作业


Github项目地址


项目相关

解题思路

拿到题目后,第一反应是需要去了解数独,去了解生成数独终盘的必要条件,之后在了解了数独之后,发现数独可随机生成6,670,903,752,021,072,936,960种组合,所以当时想着如果使用随机数,有很大概率能够直接命中,同时我也认为如果生成的数独终盘不能够有足够的随机性,那么这个数独会变得非常容易解,因此在解程序的时候,我侧重于生成的数独有着足够的随机性,因此,我采用了大量1-9随机组合去组成一个数独终盘。 (但是后面码完代码,跟同学沟通后发现其实这么侧重于随机性并不能够使程序运行速度提高很多,而且利用一定的规律能够使程序非常简单...)

关键代码or设计说明

关键代码

while (x!=9) //对数独每一行进行生成 
		{
			bool p=false; //p是数值是否可用的标记 
			int rt=0;  //rt记录随机的次数 
			while(!p && rt<20)   //对每一个数进行调整 
			{
				row=0;
				rm=rand()%(9-y);  //对当前及之后可交换位置的选取 
				rt++;
				while(row<x)  //检查选取的位置是否合法 
				{
					if (sudoku[row][y] == sudoku[x][rm+y])break; //发现前面的位置和当前数据冲突 
					else
					{
						row++;
					}
				}
				if (row==x) p=true;   //检查结束,全通过 
				else
				{
					continue; //检查未通过,重新开始 
				}
				int initR, initC;
				if (x < 3)initR = 0;
				else if (x < 6)initR = 3;
				else if (x < 9)initR = 6;
				if (y < 3)initC = 0;
				else if (y < 6)initC = 3;
				else if (y < 9)initC = 6;  //判断当前位置所在九宫 
				for (i = 0; i < x%3; i++)  //与九宫内的数进行比较 
				{
					for (int j = 0; j < 3; j++)
					{
						if (sudoku[i+initR][j+initC]==sudoku[x][rm+y])
						{
							p=false;
							j=3; //脱出循环 
							i=x%3; //脱出循环 
						}
					}
				}
				if (p)  //当前数值合法,进行交换 
				{
					swap(&sudoku[x][y],&sudoku[x][y+rm]);
				}
			}
			y=(y+1)%9;  //坐标改变 
			if (rt>=20)  //如果随机多次未能命中,则退后一行,重新生成 
			{
				if (x!=1)
				x--;
				y=0;
			}
			else if (!y) //如果y超过8,则换行 
			{
				x++;
			}
		}

设计说明

因为在题目中有特别的要求,需要以学号得出的数字开头,我学号是9,所以在初始数独时候,干脆将数独初始化成9-1的倒序排列,这样初始化能够直接满足数独在每一行由1-9组成,在之后的过程中就不需要再考虑行上的条件了,在随机取数的时候,换成将随机与同一行后置位进行调换,这样既能够做到随机,也能够简化代码,提高程序效率。若是遇到向后调换也无法满足条件的情况,我的策略是直接后退一行,这样就能够将这行数重新随机,解决问题。

遇到的困难及改进方法

困难描述

一开始打代码时的思路,是想着将矩阵置0,然后每个位置随机一个符合条件的数去填,这样打出来代码后,发现程序运行效率极低

优化尝试

在随机取数耗时极大以后,我想提高随机数的命中率,当时我想到了快排中的交换,然后我就想着如果使用交换的方法,1-9中随机交换,这样既能够保证1-9都存在,又能够提高随机的命中率。在改变了随即方法后,程序的整个效率都提高了,但是虽然提高的比较多,从总体方面看还是比较低效的。

解决后的收获

在很多时候,有很多思想其实都是互通的,因为想到了快排的做法,所以想出了对程序优化的方法,很多时候可以通过借鉴别的东西从而获得一些帮助。

程序测试运行

通过命令行运行代码后

通过vs2017的性能查探器生成的性能分析图如下

PSP + 学习进度条更新

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

学习进度条:

第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 330 330 13 13 触类旁通,学习到了一个优化思想

对"执行力"和“泛泛而谈”的理解

我对于执行力的理解大概就是将所作承诺付诸于实践中的力度吧,行动是最好的说明,将口中所说在行动中表现出来,而不是思想上的巨人,行动上的矮子,这样就是我认为的执行力的意思。
对于泛泛而谈来说,我首先不认为并不认为泛泛而谈=喊口号,说空话,喊口号,说空话可以看做是泛泛而谈,但并不是只要是泛泛而谈就是在喊口号说空话。用到一些“大概”,“尽可能多”这些词的时候,我并不认为这样的言语就是在喊口号,就是执行力不够,但从言语的角度,这些词使用肯定会降低语言的可信度,但对于实际情况来说,这些词又是最好的描述,现实不是理想,不可能事事如意,意外很多,情况很多,有时候给自己留出余地并不是坏事,把话说满却不能够做到我认为并不比说话留余地好到哪里去(当然,大家都喜欢好话更多的人这种事是肯定的)
这些意见,仅代表我个人想法,并没有什么很权威的根据之类的,如有不同见解,请多多见谅!谢谢!


                                                          2017.9.10