1.GitHub:https://github.com/laj6789-123/031702136
2.PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 20 |
Estimate | 估计这个任务需要多少时间 | 60 | 120 |
Development | 开发 | 90 | 200 |
Analysis | 需求分析 (包括学习新技术) | 60 | 120 |
Design Spec | 生成设计文档 | 45 | 60 |
Design Review | 设计复审 | 20 | 20 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
Design | 具体设计 | 25 | 40 |
Coding | 具体编码 | 700 | 600 |
Code Review | 代码复审 | 60 | 60 |
Test | 测试(自我测试,修改代码,提交修改) | 100 | 170 |
Reporting | 报告 | 180 | 230 |
Test Report | 测试报告 | 60 | 80 |
Size Measurement | 计算工作量 | 40 | 50 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 80 | 100 |
合计 | 1550 | 1900 |
题目描述
数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。
具体任务:
现在我们想一步一步来,完成从三宫格到九宫格的进阶;完成三宫格和其他博客任务,就算过了初级考核,其他的算升级。具体各阶规则如下:
三宫格:盘面是33。使1-3每个数字在每一行、每一列中都只出现一次,不考虑宫;
四宫格:盘面是22四个宫,每一宫又分为22四个小格。使1-4每个数字在每一行、每一列和每一宫中都只出现一次;
五宫格:盘面是55。使1-5每个数字在每一行、每一列中都只出现一次,不考虑宫;
六宫格:盘面是23六个宫,每一宫又分为32六个小格。使1-6每个数字在每一行、每一列和每一宫中都只出现一次;
七宫格:盘面是77。使1-7每个数字在每一行、每一列中都只出现一次,不考虑宫;
八宫格:盘面是42八个宫,每一宫又分为24八个小格。使1-8每个数字在每一行、每一列和每一宫中都只出现一次;
九宫格:盘面是33九个宫,每一宫又分为3*3九个小格。使1-9每个数字在每一行、每一列和每一宫中都只出现一次;
解题思路
因为自己从没玩过数独,百度了很多数独的解法,看到了一种自己能看懂的解法。想着从三宫格一直扩展到九宫格。三宫格的解法:将三宫格的数字编号记为0-n(n=8),num[3][3]为创建的数组,numn/3][n%3]为数组中的每个数。
核心代码
bool Check(int n, int key)//判断填入的数是否合法
{
for (int i = 0; i < jie_num; i++)//判断n所在横列是否合法
{
int j = n / jie_num; // j为n竖坐标
if (num[j][i] == key)
return false;
}
for (int i = 0; i < jie_num; i++)//判断n所在竖列是否合法
{
int j = n % jie_num; //j为n横坐标
if (num[i][j] == key)
return false;
}
if (jie_num == 4 || jie_num == 6 || jie_num == 8 || jie_num == 9)//4689 规律相似
{
int a, b; //a为每个小宫格中横向的格子数,b为纵向格子数
switch (jie_num)
{
case 4:
a = 2, b = 2;
break;
case 6:
a = 3, b = 2;
break;
case 8:
a = 2, b = 4;
break;
case 9:
a = 3, b = 3;
break;
}
int x = n / jie_num / b * b; //x为n所在的小宫格左顶点竖坐标
int y = n % jie_num / a * a; //y为n所在的小宫格左顶点横坐标
for (int i = x; i < x + b; i++)//判断n所在的小宫格是否合法
{
for (int j = y; j < y + a; j++)
{
if (num[i][j] == jie_num) return false;
}
}
}
return true; //都合法,返回正确
}
int DFS(int n)//深搜+回溯
{
int total;//每个数独中的总数—1
total = jie_num * jie_num - 1;
if (n > total)
{
sign = true;
return 0;
}
if (num[n / jie_num][n % jie_num] != 0)//当前位不为空时跳过
{
DFS(n + 1);
}
else
{
for (int i = 1; i <= jie_num; i++)//否则对当前位进行枚举测试
{
//满足条件时填入数字
if (Check(n, i) == true)
{
num[n / jie_num][n % jie_num] = i;
DFS(n + 1); // 继续搜索
if (sign == true) //返回时如果构造成功,则直接退出
{
return 0;
}
num[n / jie_num][n % jie_num] = 0;//如果构造不成功,还原当前位
}
}
}
return 0;
}
核心:DFS深度搜索+回溯法
1,搜索到数字不为0,跳过,检查下一个数字,即DFS(n+1);
2,循环遍历数组中没有标记位true的地方,也就是需要填数的地方,即Check()函数如果当前为0,即num[i][j]0,判断当前所在的宫格,然后从数字1-9依次检测是否在行、列中唯一。
满足唯一的话,则把数字赋值给num[n/jie_num][n%jie_num]=i;然后继续深度遍历为true的话就返回true,否则回溯a[i][j]0等不满足满足唯一则判断下一个数字,直到1-9都判断不满足则返回false,会回溯到上一层,如果n>8,说明都已经填满且符合唯一条件,则返回true;结束,其中还要判断小各的合法性。
主函数
#include<iostream>
#include<stdlib.h>
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
bool sign = false;/* 构造完成标志 */
int num[3][3];/* 创建数独矩阵 */
int main(int argc,char *argv[])
{
int k, i, j;
char* in; //输入文件
char* out;
jie_num = atoi(argv[2]);
pan_num = atoi(argv[4]);
in = argv[6];
ifstream infile(in);
out = argv[8];
ofstream outfile(out);
for (k = 0; k < pan_num; k++) {
char temp[10][10] = { 0 };
int flag = 0;
for (i = 0; i < jie_num; i++)
{
for (j = 0; j < jie_num; j++)
{
infile >> temp[i][j];
num[i][j] = temp[i][j] - '0';
}
flag++;
}
cout << endl;
sign = false;
DFS(0);
for (i = 0; i < jie_num; i++)
{
for (j = 0; j < jie_num; j++)
{
num2[k][i][j] = num[i][j];
}
}
for (i = 0; i < jie_num; i++)
{
for (j = 0; j < jie_num; j++)
{
cout << num2[k][i][j] << " ";
}
cout << endl;
}
cout << endl;
ofstream outfile;
outfile.open("output.txt", ios::app); //以后继方式打开文件以便继续写
for (int i = 0; i < jie_num; i++) {
for (int j = 0; j < jie_num; j++) {
outfile << num2[k][i][j] << " ";
}
outfile << endl;
}
outfile << "
";
outfile.close();
}
return 0;
}
刚开始时sign初始化为false,构造未成功,Check()函数检查数字在行列中的合法性
总结
做了这次作业,感觉自己真的很差,大一大二基础没打好造成的后果真的很严重,这次作业一直在搞文件输入输出、命令行这些,问了同学,查了百度但还是没能搞懂,所以就借鉴了同学的作业,哎很难受,以后如果能弄懂的话再修改代码吧。这次作业还有收获就是学到了github中的一些简单操作。