博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
sudoku
阅读量:4945 次
发布时间:2019-06-11

本文共 4394 字,大约阅读时间需要 14 分钟。

1.GitHub地址:https://github.com/Fionayxy/sudoku

2.

PSP2.1 Personal Software Process Stages 预计耗时(分钟) 实际耗时(分钟)
Planning 计划 60 60
Estimate 估计这个任务需要多少时间 20 20
Development 开发 1800 1200
Analysis 需求分析(包括学习新技术) 360 300
Design Spec 生成设计文档 120 150
Design Review 设计复审(和同事审核设计文档) 20 10
Coding Standard 代码规范(为目前的开发制定合适的规范) 20 30
Design 具体设计 180 200
Coding 具体编码 2000 360
Code Review 代码复审 300 180
Test 测试(自我测试,修改代码,提交修改) 60 360
Report 报告 150 150
Test Report 测试报告 30 30
Size Measurement 计算工作量 10 10
Postmortem&Process Improvement Plan 事后总结,并提出过程改进计划 60 120
  合计 5190 3180

3.解题思路

看到题目后毫无头绪,尤其是对命令行、GitHub等毫无了解而且对C++了解甚少,C#完全不会,因此一拖再拖。

后来在查询了main函数的参数意义,如何使用C++创建或打开本地文件、编辑文件,并在同学的帮助下,学会了github的皮毛。

(1)生成数独

刚开始百度如何生成数独,研究网上的代码和思路,进展十分缓慢。最后同学给我讲解了他的思路,即:

先定义第一行数字(学号尾号37,(3+7)%9+1=2)

int tmp[9] = { 2,3,4,5,6,7,8,9,1 };

之后8行的数字排列可看做是对第一行数字进行移动

 因为九宫格中的数字不能重复,因此将2-8行右移相应格数

int moveright[8] = { 3,6,1,4,7,2,5,8 };

由于第一行第一个数应保持为2不变,对其余8个数进行全排列,一共有8!=40320种

且在每一个情况下,都可变换4-6行、7-9行的位置,即每个确定的第一行都有3!×3!=36种不同的终局

因此最终可生成终局40320×36=1451520(种)>1e6(种)

全排列时用到了 <algorithm>头文件下的函数

bool next_permutation(iterator start,iterator end)

(2)解数独

采用了递归的方法,从第一个格子开始

对每个格子,如果该格已有有效数(1-9),则遍历下一格,若没有有效数,则从1-9寻找满足条件(行、列、九宫格无重复数字)的所有侯选数

遍历直至最后一个格子,输出当前数独

由于本题只要求输出一个可行解,因此在首次输出后,直接结束即可。

4.设计实现过程

int main(int argc, char *argv[])void Sudoku(int a[9][9], int n)   //数独求解函数bool check(int a[9][9], int i, int j, int k)//判断是否可以将第i行、第j列的数设为kvoid print(int a[9][9])//输出可行的解int convert(char* str)//判断输入的字符串是否均为数字(即n)void creat_shudu() //生成终局并输出到sudoku文件中

 

5.性能分析

生成500个数独终局

 

解数独测试用例

0 8 0 0 0 1 6 0 0

0 7 0 4 0 0 0 2 1
5 0 0 3 9 6 0 0 0
2 0 4 0 5 0 1 3 0
0 0 8 9 0 7 5 0 0
0 5 7 0 3 0 9 0 0
0 0 0 5 6 3 0 0 9
3 1 0 0 0 2 0 5 0
0 0 5 8 0 0 0 4 0
0 1 2 6 8 0 0 9 0
6 0 0 0 0 4 0 1 0
8 0 5 2 0 0 3 7 0
0 0 0 0 0 7 5 2 3
0 0 0 4 0 6 0 0 0
3 8 1 9 0 0 0 0 0
0 5 4 0 0 2 8 0 1
0 7 0 3 0 0 0 0 2
0 3 0 0 5 9 7 6 0
0 4 7 0 5 0 0 0 8
6 0 5 0 3 0 2 0 1
0 0 0 7 0 6 0 3 0
0 0 6 0 7 0 0 2 4
9 0 0 8 0 4 0 0 6
4 5 0 0 1 0 9 0 0
0 1 0 5 0 2 0 0 0
2 0 8 0 4 0 5 0 3
5 0 0 0 9 0 7 1 0
0 0 9 0 0 1 6 2 0
5 7 0 0 2 8 0 3 0
3 0 0 7 0 0 0 0 4
8 9 0 0 7 0 4 0 0
0 6 0 5 0 3 0 9 0
0 0 1 0 9 0 0 7 6
6 0 0 0 0 7 0 0 8
0 4 0 1 3 0 0 6 5
0 2 7 6 0 0 9 0 0

 

 

6.代码说明

(1)解数独

void Sudoku(int a[9][9], int n) {    int temp[9][9];    int i, j;    for (i = 0; i<9; i++) {        for (j = 0; j<9; j++)            temp[i][j] = a[i][j];    }    i = n / 9;    j = n % 9; //求出第n个数的行数和列数    if (a[i][j] != 0) { //已经有原始数据        if (n == 80) {  //是最后一个格子,输出可行解            print(temp);        }        else    //不是最后一个格子,求下一个格子            Sudoku(temp, n + 1);    }    else { //没有数据        for (int k = 1; k <= 9; k++) {            bool flag = check(temp, i, j, k);            if (flag) { //第i行、第j列可以是k                temp[i][j] = k; //设为k                if (n == 80) {                    print(temp);                    break;                }                else                    Sudoku(temp, n + 1);                temp[i][j] = 0; //恢复为0,判断下一个k            }        }    }}

 

(2)生成终局

void creat_shudu() //生成终局并输出到sudoku文件中{    int tmp[9] = { 2,3,4,5,6,7,8,9,1 };//tmp表示第一行数字    int i, j, k, moveright[8] = { 3,6,1,4,7,2,5,8 };    //右移位数    for (i = 0; i < 40320; i++)    //8!=40320    {        memcpy(map[0], tmp, sizeof(tmp));        for (j = 0; j < 8; j++)            for (k = 0; k < 9; k++)                map[j + 1][(k + moveright[j]) % 9] = map[0][k];//初始模板        int row[9] = { 0,1,2,3,4,5,6,7,8 };//fol函数是接下来输出的1-9行对应数独模板的fol行        for (j = 0; j < 6; j++)        {            if (j != 0)                next_permutation(row + 3, row + 6);//此函数是求4-7行的下一个排列            for (k = 0; k < 6; k++)            {                if (k != 0)                    next_permutation(row + 6, row + 9);                for (int a = 0; a < 9; a++)                {                    for (int b = 0; b < 9; b++)                    {                        if (b == 0)                            output << map[row[a]][b];                        else                            output << " " << map[row[a]][b];                    }                    output << endl;                }                output << endl;                if (!--n)                    return;            }//完成一次数独的输出            row[6] = 7, row[7] = 8, row[8] = 9;        }//每种数独模板有36种形式,最多能输出8!*36=1451520种        next_permutation(tmp + 1, tmp + 9);//对tmp函数进行一次全排列    }    return;}

 

转载于:https://www.cnblogs.com/y-x-y/p/8886415.html

你可能感兴趣的文章
检验两个随机序列的beta系数
查看>>
node-webkit教程(10)Platform Service之File dialogs
查看>>
《计算机组成与体系结构:性能设计》读后小记 5、内部存储器
查看>>
3 基础语法
查看>>
字符串知识储备
查看>>
unity之截屏功能
查看>>
直连网(directly-connected networks)个数的计算
查看>>
javascript面对对象编程指南 第一章
查看>>
poj 2773 happy2006
查看>>
ADO.NET基础知识学习(SQLCOnnection&SQLCommand&SQLDataReader&SQLDataAdapter&DataSet)
查看>>
《Java核心技术》 -- 读书笔记 ① - 预热
查看>>
关系管理系统:Web层controller控制页面Servlet AddCustomerServlet
查看>>
Eclipse MAT插件下载地址
查看>>
采样电阻选型
查看>>
数据库编程:数据库删除数据不支持表别名
查看>>
tar命令详解
查看>>
Python爬虫番外篇之Cookie和Session
查看>>
Windows脚本 - Bat批处理命令使用教程
查看>>
原生与jQuery封装的ajax请求数据及状态码
查看>>
2018-2019-2 网络对抗技术 20165301 Exp2 后门原理与实践
查看>>