写在前头:最后一门补考时间09.10 16:00
Github地址: git
解题思路:
-一开始收到题目时候因为在准备补考没有时间而且因为代码基础比较薄弱所以自己没有什么思路。因此上网搜索解题思路。
-本来准备用的c#,不过因为网上的代码看不懂,勉强看出用的是变换法,所以改用c++
-网上c++关于数独的解法看下来大致分成了变换法或者回溯法.
设计实现:
-首先是开始的时候每个格子都能填入9个数,除了已经确定的第一个格子【1,1】是4,以及所在的行和列。要实现的就是逐渐把这些待选的数填进去,当然同时更新相关格子的待选数。
-计算时先挑出待选数最少的格子,从这个格子的待选数中选一个填进去,然后更新相关格子的待选数,逐步测试。
-从网上看到上一步的想法可以用递归来实现
主要代码:
//用来填数的函数//
void add(int r, int c, int num)
{
++first;
a[r][c] = num;
for (int i = 0; i<9; ++i)
{
if (a[r][i] == 0 && second[r][i].test(num))
{
second[r][i].reset(num);
--choosenum[r][i];
flags[r][i].set(first);
}
if (a[i][c] == 0 && second[i][c].test(num))
{
second[i][c].reset(num);
--choosenum[i][c];
flags[i][c].set(first);
}
}
int pr = r>2 ? (r>5 ? 6 : 3) : 0;
int pc = c>2 ? (c>5 ? 6 : 3) : 0;
for (int i = 0; i<3; ++i)
{
for (int j = 0; j<3; ++j)
{
r = pr + i;
c = pc + j;
if (a[r][c] == 0 && second[r][c].test(num))
{
second[r][c].reset(num);
--choosenum[r][c];
flags[r][c].set(first);
}
}
}
}
//用来寻找最优的还未填数的格子//
bool find(int &r, int &c)
{
int min = 999;
for (int i = 0; i<9; ++i)
{
for (int j = 0; j<9; ++j)
{
if (a[i][j] == 0 && choosenum[i][j]>1 && choosenum[i][j]<min)
{
r = i;
c = j;
min = choosenum[i][j];
}
}
}
if (min == 999)
return false;
return true;
}
测试运行:
性能分析:测试数据100
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 70 |
Estimate | 估计任务时间 | 30 | 45 |
Development | 开发 | 1200 | 1320 |
Analysis | 需求分析 | 120 | 150 |
Design | 生成设计文档 | 0 | 0 |
Design Review | 设计复审 | 0 | 0 |
Coding Standard | 代码规范 | 0 | 0 |
Design | 具体设计 | 60 | 80 |
Coding | 具体编码 | 120 | 160 |
Code Review | 代码复审 | 45 | 40 |
Test | 测试 | 180 | 150 |
Reporting | 报告 | 120 | 120 |
Test Repor | 测试报告 | 30 | 45 |
Size Measurement | 计算工作量 | 0 | 0 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 45 | 45 |
合计 | 2010 | 2225 |
反思:
1.做的过程中可能是因为不规范的原因上述PSP表中很多步骤都没有用到。
2.整道题的思路是跟着网上的资料来走的,如果没有资料大概会一筹莫展,希望通过学习能够做到已拿到题目就有自己的思路。