2019软工第三次作业

准备阶段

1、github地址

2、PSP表格

psp2.1预估耗时(分钟)实际耗时(分钟)
计划3030
估计这个任务需要多少时间2015
开发150120
需求分析 (包括学习新技术)240300
生成设计文档2030
设计复审1010
代码规范(为目前的开发制定合适的规范)120120
具体设计3030
具体编码240180
代码复审2015
测试(自我测试,修改代码,提交修改)120240
报告3060
测试报告3050
计算工程量2030
事后总结,并提出过程改进计划6060
合计11401290

开始阶段

1、思考

1448630-20190920203646776-695560240.png

百度百科简介:
数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。

对于从来没有接触过数独的我来讲,这无疑是一个非常、非常、非常难的题目,因为我连最基本的数独规则都不清楚。即使它只有三条判断逻辑,但是解一个九宫格数独,还是需要一定的时间的。

2、思路

首先判断、利用三个bool数组直接获得合法性结果。

 if(row[x][i] == false && col[y][i] == false && little_shudu[area][i] == false)
 

如此之后,我们可以得到一个方格是否能进行填入的结果。
得到方块的合法性之后,我们用DFS进行遍历、回溯

                shudu[x][y] = i;
                row[x][i] = true;
                col[y][i] = true;
                if(gx != 1 || gy != 1)
                    little_shudu[area][i] = true;
                dfs(index + 1,maxscan,jie,gx,gy);
                shudu[x][y] = 0;
                row[x][i] = false;
                col[y][i] = false;
                if(gx != 1 || gy != 1) 
                    little_shudu[area][i] = false;

3、模块

1、输入模块

由于要求是要从input.txt中输入,所以输入模块如下:

void input(int x,int gx,int gy)
{
    memset(row,false,sizeof(row));
    memset(col,false,sizeof(col));
    memset(little_shudu,false,sizeof(little_shudu));
    for(int i = 0 ; i < x ; i++){
        for(int j = 0 ; j < x ; j++){
            fscanf(fp, "%d", &shudu[i][j]);
        
            int temp_i = i / gx;
            int temp_j = j / gy;
            int area = temp_i * gx + temp_j;
        
            if(shudu[i][j] != 0){
                int temp = shudu[i][j];
                row[i][temp] = true;
                col[j][temp] = true;
                if(gx != 1 || gy != 1 ){
                    little_shudu[area][temp] = true;
                }
                
            }
        }
    }
}
2、输出模块

通过输入文件得到数独并进行求解,然后将其输出一个output.txt文件

void print(int x)
{
    for(int i = 0 ; i < x ; i++)
    {
        for(int j = 0 ; j < x ; j++)
        {
            if(j == x - 1) {
                fprintf(fp, "%d\n", shudu[i][j]);
            
            }
            else {
                fprintf(fp, "%d ", shudu[i][j]);
            
            }
        }
    }
    fprintf(fp, "\n");
    
}
3、求解模块

即先检查合法性,后进行计算填入。

void dfs(int index , int maxscan,int jie,int gx , int gy)
{
    if(index >= maxscan) 
    {
        print(jie);
        return ; 
    }
    int x = index / jie ;
    int y = index % jie ;
    int temp_i = x / gx;
    int temp_j = y / gy;
    int area = temp_i * gx + temp_j;
    if(shudu[x][y] == 0)
    { 
        for(int i = 1 ; i <= jie ; i++)
        {
            if(row[x][i] == false && col[y][i] == false && little_shudu[area][i] == false)
            {
                shudu[x][y] = i;
                row[x][i] = true;
                col[y][i] = true;
                if(gx != 1 || gy != 1)
                    little_shudu[area][i] = true;
                dfs(index + 1,maxscan,jie,gx,gy);
                shudu[x][y] = 0;
                row[x][i] = false;
                col[y][i] = false;
                if(gx != 1 || gy != 1) 
                    little_shudu[area][i] = false;
            }
        }
    }
    else{
        dfs(index + 1,maxscan,jie,gx,gy);
    }
}

4、性能测试

1797440-20190924000744987-1650825081.png

感觉好像还行,不明觉厉。

5、运行测试

1797440-20190924001504651-1735356729.png
1797440-20190924001520419-1057223862.png
三宫格 done!

1797440-20190924001659447-728827670.png
1797440-20190924001713157-1927618371.png
四宫格 done!

(中间省略5 6 8)

1797440-20190924001222504-209549368.png
1797440-20190924001237048-1488206605.png
七宫格 done!

1797440-20190924002124562-1459912313.png
1797440-20190924002202234-32792001.png
当然肯定也少不了九宫格!
总代码:

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include<string>
#include <cstring>
#include <set>
#include <map>
#include <cmath>
#include <stack>
#include <queue>
#include <fstream>

using namespace std;
const int maxn = 1000;
const int sizen = 16;
int shudu[sizen][sizen];//存储数独
bool row[sizen][sizen];//row[i][j]判断i行j是否被填过
bool col[sizen][sizen];//col[i][j]判断i列j是否被填过
bool little_shudu[sizen][sizen];//little_sudu[i][j]判断从左往右开始的第i个小数独中,j是否被填过;
FILE* fp;

void input(int x, int gx, int gy) {
    memset(row, false, sizeof(row));
    memset(col, false, sizeof(col));
    memset(little_shudu, false, sizeof(little_shudu));
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < x; j++) {

            scanf("%d", &shudu[i][j]);
            int temp_i = i / gx;
            int temp_j = j / gy;
            int area = temp_i * gx + temp_j;

            if (shudu[i][j] != 0) {
                int temp = shudu[i][j];
                row[i][temp] = true;
                col[j][temp] = true;
                if (gx != 1 || gy != 1) {
                    little_shudu[area][temp] = true;

                }

            }
        }
    }
}
void print(int x) {
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < x; j++) {
            if (j == x - 1) {


                printf("%d\n", shudu[i][j]);
            }
            else {

                printf("%d ", shudu[i][j]);
            }
        }
    }

    printf("\n");
}
void dfs(int index, int maxscan, int jie, int gx, int gy) {
    if (index >= maxscan) {
        print(jie);
        return;
    }
    int x = index / jie;
    int y = index % jie;
    int temp_i = x / gx;
    int temp_j = y / gy;
    int area = temp_i * gx + temp_j;
    if (shudu[x][y] == 0) {
        for (int i = 1; i <= jie; i++) {
            if (row[x][i] == false && col[y][i] == false && little_shudu[area][i] == false) {
                shudu[x][y] = i;
                row[x][i] = true;
                col[y][i] = true;
                if (gx != 1 || gy != 1)
                    little_shudu[area][i] = true;
                dfs(index + 1, maxscan, jie, gx, gy);
                shudu[x][y] = 0;
                row[x][i] = false;
                col[y][i] = false;
                if (gx != 1 || gy != 1)
                    little_shudu[area][i] = false;
            }
        }

    }
    else {
        dfs(index + 1, maxscan, jie, gx, gy);
    }
}

int main(int argc, char *argv[]) {
    int pan, size, jie, gx, gy;
    int in, out;
    for (int i = 0; i < argc; i++)
    {
        if (strlen(argv[i]) == 1)
        {
            if (i == 2)
                size = atoi(argv[i]);
            if (i == 4)
                pan = atoi(argv[i]);
        }
        else if (argv[i][0] == '-' && argv[i][1] == 'i') {
            i++;
            in = i;
        }
        else if (argv[i][0] == '-' && argv[i][1] == 'o') {
            i++;
            out = i;
        }
    }
    freopen(argv[in], "r", stdin);
    freopen(argv[out], "w", stdout);
    jie = size;
    if (size == 4) {
        gx = gy = 2;
    }
    else if (size == 6) {
        gx = 2;
        gy = 3;
    }
    else if (size == 8) {
        gx = 4;
        gy = 2;
    }
    else if (size == 9) {
        gx = gy = 3;
    }
    else gx = gy = 1;
    for (int i = 0; i < pan; i++) {
        input(size, gx, gy);

        dfs(0, jie*jie, jie, gx, gy);

    }
    return 0;
}

尾声

总结

在众多大佬的帮助下,终于是完成了这次作业。通过这次的作业,更是学到了不少东西,典型的就是github。希望能够在以后的学习中,更上一层楼。

转载于:https://www.cnblogs.com/Pr0Sk1er/p/11576063.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值