因为git和vs以前做计算器的时候用过 使用起来还是蛮熟悉的。
解题思路
数独是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复。 数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。
简单的了解下数独就是每一行,每一列,每一小九宫格的数字均为1-9,且每个数字只出现一次不重复。
故这题就是用一个数组flag标记该位置是否可填数字,如果可填,通过get_next_num(int,int,int)找到可行数字并且填入到Sudoku[][]中去 ,然后进入下一层递归,如果获取不了就返回上一层递归。
解法No.1:刚开始我是想每次标记的时候都把整行,整列,以及整个小九宫格遍历一遍,寻找是否该数字可用,觉得这样子很耗时间。
解法No.2:现在我们在算法中用了 row_mark[][] col_mark[][] J_Gong_mark[][]三个数组来标记该行数字是否用过,该列数字是否用过,以及该小九宫格是否用过这数字。方便后面检查。
比如说某一行的某个数字用过就用数组 row_mark [第几行][哪一个数字] = 1 做标记
再比如说某一列的某个数字用过就用数组col_mark[第几列][哪一个数字] = 1 做标记
某一小九宫格的某个数字用过就用数组J_Gong_mark[第几个小九宫格][哪一个数字] = 1 做标记 //PS: 小九宫格位置计算 3*(行/3)+(列/3)
这样子我们可以减少查询次数,节省了一大部分时间。
flag[][]数组,它用来标记,哪些位置是可以填数的,换句话来说,哪些位置,在初始状态是空的。初始完后,我们用回溯法,从第一个位置开始寻找,从三个数组中找交集即(row_mark col_mark J_Gong_mark ) 也就是说这三个数组都没标记这个数字 说明该数字是可以用的,如果当前数可用,就进入下一层的递归,直到到达最后一个格子。
还有本算法可以通过递归找到你所需要填的的几个数独棋盘。由于我们每次寻找的都是可用数字,不用判断当前数是否符合规则。
代码
//进行回溯 加 遍历
void sudokulib::backdate(int x, int y) {
if (y == 9) x++, y = 0;
while (flag[x][y] && x <= 8) {
y++;
if (y == 9) {
x++, y = 0;
}
}
if (x > 8) {
print();
if (++cnt == N) {
exit(-1);
}
}
while ((sudoku_tmp[x][y] = get_next_num(x, y, sudoku_tmp[x][y] + 1)) != -1) {
row_mark[x][sudoku_tmp[x][y]] = 1;
col_mark[y][sudoku_tmp[x][y]] = 1;
J_Gong_mark[3 * (x / 3) + (y / 3)][sudoku_tmp[x][y]] = 1; //说明该数字可以用
backdate(x, y + 1);
row_mark[x][sudoku_tmp[x][y]] = 0;
col_mark[y][sudoku_tmp[x][y]] = 0;
J_Gong_mark[3 * (x / 3) + (y / 3)][sudoku_tmp[x][y]] = 0; //说明该数字不能用 还原到前一个状态
}
}
运行结果
性能测试
以下是我跑100W数据的性能分析:
从图中可以看出该程序还是挺慢的 !!跑100W数据都得6分多钟。感觉要改进的话就应该用数字字符,可能跑的速度会快一点。
单元测试
这一块还不怎么懂,看百度一些资料1 资料2自己也尝试了,一直调试不出结果。Orz......
简简单单的记录
.初次记录 有点乱 也不知道什么作用 希望后面能明白 迷迷糊糊....
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 70 |
· Estimate | · 估计这个任务需要多少时间 | 420 | 440 |
Development | 开发 | 120 | 150 |
· Analysis | · 需求分析 (包括学习新技术) | 90 | 100 |
· Design Spec | · 生成设计文档 | 60 | 60 |
· Design Review | · 设计复审 (和同事审核设计文档) | 20 | 20 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 100 | 120 |
· Design | · 具体设计 | 30 | 30 |
· Coding | · 具体编码 | 60 | 70 |
· Code Review | · 代码复审 | 60 | 60 |
· Test | · 测试(自我测试,修改代码,提交修改) | 100 | 100 |
Reporting | 报告 | 60 | 60 |
· Test Report | · 测试报告 | 30 | 30 |
· Size Measurement | · 计算工作量 | 20 | 20 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 30 |
合计 | 1250 | 1360 |
心得体会
做这个任务的时候发现已经快开学了,所以自己也提前回学校来学习如何处理这个任务,也去看了很多资料,看了很多前辈们的做法和优化。在这个过程中最让人头疼的是使用vs做性能测试和单元测试,到现在为止单元测试还是没搞明白,但在这过程中还是学会了蛮多的,至少现在看到了vs的强大(可能还有更强大的功能需要我们在这过程中慢慢去发觉),我觉得这才刚刚开始,接下来会更好玩........