evelyn_j

导航

数独

---恢复内容开始---

一、Github地址: https://github.com/xiaxiaxiaxiajie/sudoku1962

 

二、PSP

 

PSP2.1  

Personal Software Process Stages    

预估耗时

(分钟)

实际耗时

(分钟)

Planning

计划

40

35

·Estimate

·估计这个任务需要多少时间

20

20

Development

开发

1100

1200

·Analysis

·需求分析(包括学习新技术)

180

210

·Design Spec

·生成设计文档

120

150

·Design Review

·设计复审

30

20

·Coding Standard

·代码规范

30

30

·Design

·具体设计

240

270

·Coding

·具体编码

1200

1000

·Code Review

·代码复审

120

300

·Test

·测试

60

120

Reporting

报告

120

120

·Test Report

·测试报告

30

20

·Size Measurement

·计算工作量

10

10

·Postmortem&Process Improvement Plan

·事后总结并提出过程改进计划

80

80

 

合计

3260

3585

 

 

 

三、解题思路:

  拿到题目看到要求时,有些词不知道是什么,感觉很麻烦,因此有不想做的心理(就是懒,真不好),开始着手分析题目后,首先要下手的就是代码部分,代码根据题目要求一共有两块,一块是解数独部分,一块是生成数独部分。

 

1. 解数独:

  用dfs从第一排开始到最后一排,依次找到空格,从数字1到9循环,判断是否能填该数字(即当前数字所处横排、竖排、九宫格是否有该数字出现过),可以填,接着往下的dfs,不可以换数字,如果没有可填的数字,返回上一次。

2.生成数独终局

  例如一个简单的数独以9为第一个数字(学号62:6+2+1=9)

  9  1  2    3  4  5    6  7  8

  3  4  5    6  7  8    9  1  2

  6  7  8    9  1  2    3  4  5

 

  1  2  3    4  5  6    7  8  9

  4  5  6    7  8  9    1  2  3

  7  8  9    1  2  3    4  5  6

 

  2  3  4    5  6  7    8  9  1

  5  6  7    8  9  1    2  3  4

  8  9  1    2  3  4    5  6  7

 

  除了第一排第一个数之外,第一排的任意数的位置均可改变,个数为 8! = 40320 种,4、5 、6行可互换位置,7、8、9行可互换位置,即有 8! *  3!* 3! > 1e6  种。

 

四、代码设计

int main(int argc, char *argv[])  //主函数, 获取命令参数

bool judge(char *s)//判断输入的数是否有效

void creat_sudoku()//生成数独终局函数

void get_init()//在解数独中对应给定的数独对三个状态数组进行初始化

void dfs(int x, int y)//解数独函数,用dfs深度优先搜索

bool judge_shudu(int x, int y, int n)//判断x行y列这个位置是否可以放置数字n

void output()//打印函数,将数独输出到指定的txt文件中

 

 

五、关键代码展示

1. 生成终局

void creat_sudoku()//生成数独终局函数
{
    m = 0;//记录当前生成多少个数独,n是要生成的数独数
    int tmp[10] = { 0,9,1,2,3,4,5,6,7,8 };//tmp 1-9是第一行要生成的数
    int moveleft[10] = { 0,0,3,6,1,4,7,2,5,8 };    //moveleft表示2-9行在第1行基础上整体左移位数
    for (int i = 1; i <= 40320; i++)    //8!=40320
    {
        for (int j = 1; j <= 9; j++)
            shudu[1][j] = tmp[j];

        for (int j = 2; j <= 9; j++)
        {
            for (int k = 1; k <= 9; k++)
            {
                int pos = k - moveleft[j];
                if (pos <= 0) pos += 9;
                shudu[j][k] = shudu[1][pos];
            }
        }//生成一个数独模板

        int fol[10] = { 0,1,2,3,4,5,6,7,8,9 };//fol函数是接下来输出的1-9行对应数独模板的fol行
        for (int j = 1; j <= 6; j++)
        {
            if (j != 1)next_permutation(fol + 4, fol + 7);//此函数是求4-7行的下一个排列
            for (int k = 1; k <= 6; k++)
            {
                if (k != 1)next_permutation(fol + 7, fol + 10);
                for (int p = 1; p <= 9; p++)
                {
                    for (int q = 1; q <= 9; q++)
                    {
                        if (q == 1)Output << shudu[fol[p]][q];
                        else Output << " " << shudu[fol[p]][q];
                    }
                    Output << endl;
                }
                Output << endl;
                if (++m >= n)
                    return;
            }//完成一次数独的输出
            fol[7] = 7, fol[8] = 8, fol[9] = 9;
        }//每种数独模板可以输出36种子数独,所以最多能输出8!*36=1451520种
        next_permutation(tmp + 2, tmp + 10);//对tmp函数进行一次全排列
    }
    return;
}

 

2. 解数独

 

void dfs(int x, int y)//解数独函数,用dfs深度优先搜索
{
    if (flag) return;
    if (y > 9) {
        x++; y = 1;
    }
    if (x == 10 && flag == 0) {
        output();
        flag = 1;
        return;
    }//此时每一位都放置了数字,则输出

    if (!shudu[x][y])
    {
        for (int i = 1; i <= 9 && !flag; i++)
        {
            if (judge_shudu(x, y, i))
            {
                line[x][i] = 1;
                orl[y][i] = 1;
                block[getblocknum(x, y)][i] = 1;
                shudu[x][y] = i;
                dfs(x, y + 1);
                line[x][i] = 0;
                orl[y][i] = 0;
                block[getblocknum(x, y)][i] = 0;
                shudu[x][y] = 0;
            }
        }
    }
    else dfs(x, y + 1);
}//判断x行y列要放置1-9中的哪一位数字,递归实现

 

3. 单元测试  

  命令行参数测试: -c  -s  -1  -a

  运行情况:-c 1  -c 1000   -c 100000   -s 文件路径 

 

六、性能分析

1. 生成1000个数独终局

 

  

 

 

2. 生成1e6个数独

 

 

3. 解1个数独

 

 

 

4. 解10个数独

 

5. 解1000个数独

 

 

 

 

 

---恢复内容结束---

posted on 2018-04-15 14:57  evelyn_j  阅读(347)  评论(0编辑  收藏  举报