zoukankan      html  css  js  c++  java
  • 2019软件工程实践第三次作业

    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每个数字在每一行、每一列中都只出现一次,不考虑宫;
    四宫格:盘面是2
    2四个宫,每一宫又分为22四个小格。使1-4每个数字在每一行、每一列和每一宫中都只出现一次;
    五宫格:盘面是5
    5。使1-5每个数字在每一行、每一列中都只出现一次,不考虑宫;
    六宫格:盘面是23六个宫,每一宫又分为32六个小格。使1-6每个数字在每一行、每一列和每一宫中都只出现一次;
    七宫格:盘面是77。使1-7每个数字在每一行、每一列中都只出现一次,不考虑宫;
    八宫格:盘面是4
    2八个宫,每一宫又分为24八个小格。使1-8每个数字在每一行、每一列和每一宫中都只出现一次;
    九宫格:盘面是3
    3九个宫,每一宫又分为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中的一些简单操作。

  • 相关阅读:
    oracle学习6
    oracle学习5
    oracle学习4
    oracle学习3
    oracle的过滤与排序
    poj1064 Cable master
    poj3169 Layout
    UVA
    poj2341 Expedition
    poj3617 Best Cow Line
  • 原文地址:https://www.cnblogs.com/aiqi6/p/11581774.html
Copyright © 2011-2022 走看看