软件工程实践2017第二次作业

本文介绍了一种利用回溯法解决数独问题的算法实现,详细解析了算法思路与核心代码,并通过实例测试验证了解法的有效性。

===================

一、GitHub地址:https://github.com/xiaoknownothing/Fzuwork

二、遇到的困难及解决方法

 一看到这个题目感觉可以选定一个空位,扫看所在行,所在列,所在宫,排除数字后选择数字填入,最好的情况所在行列的数字全部填满,这样就简单多了。可是这个数独棋盘只有一个数已知,其他的位子都有9个数要去“猜测”,每行每列每宫格子内数字还不重复,顿时脑子有点大,忙着搜索了一下,看了一些博客,才有了一些大概方向。

三、解题思路

用回溯法求解数独:

  • 1.从找第一个空的位子开始,找可选数(排除同行同列同宫重复的数),逐个放入
  • 2.找下一个空的位置,找可选数填入,如果这时候,发现此处空白格没有可选数,就回溯,换掉前面的可选数,再继续执行2
  • 3.直到空位子都满了就是一个数独解出来了
    //找出area[x][y]的可选数
vector <int> find(int x, int y) 
{
    int a[10] = { 0 };
    vector <int> ret;//声明一个int型向量ret 
    for (int i = 0; i < 9; i++)
     {
        if (sudu[i][y] > 0) 
        a[sudu[i][y]] = 1;//所在行若有其他数,标记已使用 
        if (sudu[x][i] > 0)
        a[sudu[x][i]] = 1; //所在列若有其他数,标记已使用 
        
    }
    int row = x / 3, col = y / 3;//所在宫若有其他数,标记已使用 
    for (int i = row * 3; i < row * 3 + 3; i++)
    { 
        for (int j = col * 3; j < col * 3 + 3; j++)
         {
            if (sudu[i][j] > 0) 
            a[sudu[i][j]] = 1;
        }
    }
    for (int i = 1; i <= 9; i++) 
    {
    if (!a[i]) ret.push_back(i);//逐个填入剩余可选数 
    }
    return ret;
}
void update() {
    for (int i = 0; i < 81; i++) area[i].clear();
    chosen = make_pair(0, 10);
    can_update = false;
    for (int i = 0; i < 9; i++  )
    {
        for (int j = 0; j < 9; j++) if (sudu[i][j]==0) 
        {
            int k = i * 9 + j;//k为该空白格序号 
            area[k] = find(i, j);//填入可选数 
            if (area[k].empty()) is_blank = false;//没有可选数 
            if (area[k].size() < chosen.second) chosen = make_pair(k, area[k].size());//更新 
            can_update = true;
        }
    }
}
void num_sudu() 
{
    update();
    if (can_update==false)
     {
        num++;
        if (num >=N) is_over = true;
        print();
    }
    else if (is_blank==false) 
    {
        return;
    }
    else if (is_over==false)
     {
        int areaition = chosen.first;
        int x = areaition / 9;
        int y = areaition - x * 9;//x,y为该位置坐标 
        int size = chosen.second;//size为选中数个数 
        vector <int> k = area[areaition];
        for (int i = 0; i < size; i++) 
        {
            sudu[x][y] = k[i];
            num_sudu();
            sudu[x][y] = 0;
            is_blank = true;
            // 回溯, 还原数据, 原is_blank, 前面的深搜,都没有正确答案,会导致is_blank=false
        }
    }
}

四、测试

  • 运行测试
    1227833-20170911123512188-864518452.png
    1227833-20170911123524188-820895583.png

五、PSP

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

转载于:https://www.cnblogs.com/xiao2017/p/7502581.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值