201971010146-杨凯 实验二 软件项目工程个人项目 《0-1背包问题》项目报告

201971010146-杨凯 实验二 软件工程个人项目 《0-1背包问题》项目报告

项目
课程班级博客链接 [2022年春软件工程课程班(2019级计算机科学与技术)](首页 - 2022年春软件工程课程班(2019级计算机科学与技术) - 西北师范大学 - 班级博客 - 博客园 (cnblogs.com))
这个作业要求链接 [实验二 软件工程个人项目 ](实验二 软件工程个人项目 - 作业 - 2022年春软件工程课程班(2019级计算机科学与技术) - 班级博客 - 博客园 (cnblogs.com))
我的课程学习目标 (1) 掌握软件项目个人开发流程
(2) 掌握Github发布软件项目的操作方法
帮助我实现学习目标 (1) 掌握了psp流程
(2) 掌握了Github发布软件项目的操作方法
(3) 复习了背包问题的各种解决方法
项目Github的仓库链接 KP项目

任务1:

任务2(构建之法第一、二章总结):

第一章:

  • 软件 = 程序 + 软件工程(软件企业 = 软件 + 商业模式 )
  • 软件的生命周期: 软件需求、软件设计、软件构造、软件测试、软件维护。
  • 软件工程:软件工程是把系统的、有序的、可量化的方法应用到软件的开发、运营和维护上的过程。
  • 软件工程包括下列领域:
    • 软件需求分析
    • 软件设计
    • 软件构建
    • 软件测试
    • 软件维护。
  • 软件工程和下列的学科相关:
    • 计算机科学
    • 计算机工程
    • 管理学
    • 数学
    • 项目管理学
    • 质量管理
    • 软件人体工学
    • 系统工程
    • 工业设计和用户体验设计。
  • 软件的特殊性:复杂性、不可见性、易变性、非连续性。
  • 软件工程的目标:创造出用户满意度高,可靠性高,软件流程质量高,可维护性高的软件。

第二章(个人技术和流程):

  • 效能分析工具:

    • 抽样:
    • 代码注入
  • PSP有如下的特点:

​ 1. 不局限于某一种软件技术(如编程语言),而是着眼于软件开发的流程,这样,开发不同应用的软件工程师可以互相比较;

​ 2. 不依赖于考试,而主要靠工程师自己收集数据,然后分析,提高;

​ 3. 在小型、初创的团队中,很难找到高质量的项目需求,这意味着给程序员的输入质量不高。在这种情况下,程序员的输出(程序/软件)往往质量也不高,然而这并不能全部由程序员负责;

​ 4. PSP依赖于数据:

​ 需要工程师输入数据,记录工程师的各项活动,这本身就需要不小的时间代价

​ 如果数据不准确或有遗失,怎么办?让工程师编造一些?

​ 如果一些数据不利于工程师本人(例如:花很多时间修改缺陷),我们怎么能保证工程师愿意如实地记录这些数据呢?

​ 5. PSP的目的是记录工程师如何实现需求的效率,而不是记录顾客对产品的满意度。

任务3(项目开发):

一、 需求分析:

  1. 使用贪心算法,动态规划算法,回溯算法求解(0-1)背包问题。
  2. 正确读入实验数据文件有效KP数据。
  3. 绘制某组KP数据以价值重量为横轴,价值为纵轴的数据散点图。
  4. 能够对一组KP数据按重量比进行非递增排序。
  5. 用户能够自主选择贪心算法、动态规划算法、回溯法。
  6. 任意一组KP数据的最优解,求解时间保存到文件中。

二、 功能设计:

graph TB; 基本功能-->读入实验数据文件 基本功能-->用户自主选择算法 用户自主选择算法-->贪心算法 用户自主选择算法-->动态规划算法 用户自主选择算法-->回溯法 基本功能-->KP数据最优解,求解时间保存到文件 基本功能-->对一组KP数据按照重量比进行非递增排序

三、 设计实现:

1. 读入实验数据文件:
	FILE *fp;
    char filename[30],x[31];
    cout<<"测试文件:\n"; 
    cout<<"beibao0.in\nbeibao1.in\nbeibao2.in\nbeibao3.in\n";
    cout<<"beibao4.in\nbeibao5.in\nbeibao6.in\nbeibao7.in\nbeibao8.in\nbeibao9.in\n";
    cout<<"请输入测试数据文件名(带后缀):\n";
    gets(filename);
    if((fp=fopen(filename,"r+"))==NULL){
        printf("ERROR!\n");
        exit(0);
    }
	fscanf(fp,"%d %d", &C, &n);
	printf("背包容量为: %d,物品个数为: %d\n", C, n);
	for(int i = 0; i < n; i++)
    {
		fscanf(fp, "%d %d",&goods[i].wight,&goods[i].value);
        printf("%d %d\n", goods[i].wight,goods[i].value); 
    }

​ 从文件中读取数据采用了c++的文件输入输出流,从键盘中获取到文件名之后,采用fopen(filename, "r+")打开文件,然后逐行读取。

2.用户自主选择算法:

​ 使用switch语句:

	switch(x){
			case 1:
				动态规划算法···
	    		break;
	    	case 2:
	    		贪心算法···
			    break;
	    	case 3:
            	回溯算法···
	    		break;
		}
  • 动态规划算法:
int KnapSack2(int n,struct goods a[],int C,int x[]){
    int V[N][10*N];
    for(int i = 0; i <= n; i++)//初始化第0列
        V[i][0] = 0;
    for(int j = 0; j <= C; j++)//初始化第0行
        V[0][j] = 0;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= C; j++)
        if(j < a[i-1].wight)
            V[i][j] = V[i-1][j];
        else
            V[i][j] = MAX(V[i-1][j],V[i-1][j-a[i-1].wight] + a[i-1].value);

    for(int i = n,j = C; i > 0; i--){
        if(V[i][j] > V[i-1][j]){
            x[i-1] = 1;
            j = j - a[i-1].wight;
        }
        else
            x[i-1] = 0;
    }
    return V[n][C];
}
  • 贪心算法:
int KnapSack1(int i){
	if(i>n-1){
	    if(bestValue < cv && cw + goods[i].wight <= C){
	        for(int k=0;k<n;k++)
	            X[k] = cx[k];//存储最优路径
	        bestValue = cv;
	    }
	    return bestValue;
	}
	cw = cw + goods[i].wight;
	cv = cv + goods[i].value;
	cx[i] = 1;//装入背包
	KnapSack1(i+1);
	cw = cw-goods[i].wight;
	cv = cv-goods[i].value;
	cx[i] = 0;//不装入背包
	KnapSack1(i+1);
	return bestValue;
} 
  • 回溯算法:
int BackTrack(int i){
    if(i > n-1){
        if(bestValue < cv){
            for(int k = 0; k < n; k++)
                X[k] = cx[k];//存储最优路径
            bestValue = cv;
        }
        return bestValue;
    }
    if(cw + goods[i].wight <= C){//进入左子树
        cw += goods[i].wight;
        cv += goods[i].value;
        cx[i] = 1;//装入背包
        BackTrack(i+1);
        cw -= goods[i].wight;
        cv -= goods[i].value;//回溯,进入右子树
    }
    cx[i] = 0;//不装入背包
    BackTrack(i+1);
    return bestValue;
}

bool m(struct goods a, struct goods b){
    return (a.value/a.wight) > (b.value/b.wight);
}

int KnapSack3(int n, struct goods a[], int C,int x[N]){
    memset(x,0,sizeof(x));
    sort(a,a+n,m);//将各物品按单位重量价值降序排列
    BackTrack(0);
    return bestValue;
} 
3. KP数据最优解及运行时间保存到文件:
  • 最优解和运行时间的计算

    • 最优解的计算:

      获取三个算法所求得的bestValue返回输出。

    • 运行时间的计算:

      需要用到:

      #include <time.h>  
      #include <windows.h>
      #include <stdio.h>  
      

      三个库函数,然后用结束运行的时间减去开始运行的时间就是运行的时间:

      time(&start);  
      ···代码运行···
      time(&end);  
      cost=difftime(end,start)
      

  • 最优解和运行时间的保存:

    ofstream outfile;
    outfile.open("beibao.out");
    outfile<<sum2<<"  运行时间: "<<cost<<endl;
    outfile.close();
    
4. 对一组KP数据按照重量比进行非递增排序:
int KnapSack3(int n, struct goods a[], int C,int x[N]){
    memset(x,0,sizeof(x));
    sort(a,a+n,m);//将各物品按单位重量价值降序排列
    BackTrack(0);
    return bestValue;
} 

四、测试运行

1. 读入实验数据及算法选择:

2. 输出结果保存到文件中:

五、代码

int KnapSack3(int n, struct goods a[], int C,int x[N]){
    memset(x,0,sizeof(x));
    sort(a,a+n,m);//将各物品按单位重量价值降序排列
    BackTrack(0);
    return bestValue;
}
	FILE *fp;
    char filename[30],x[31];
    cout<<"测试文件:\n"; 
    cout<<"beibao0.in\nbeibao1.in\nbeibao2.in\nbeibao3.in\n";
    cout<<"beibao4.in\nbeibao5.in\nbeibao6.in\nbeibao7.in\n";
    cout<<"请输入测试数据文件名(带后缀):\n";
    gets(filename);
    if((fp=fopen(filename,"r+"))==NULL){
        printf("ERROR!\n");
        exit(0);
    }
	fscanf(fp,"%d %d", &C, &n);
	printf("背包容量为: %d,物品个数为: %d\n", C, n);
	for(int i = 0; i < n; i++)
    {
		fscanf(fp, "%d %d",&goods[i].wight,&goods[i].value);
        printf("%d %d\n", goods[i].wight,goods[i].value); 
    }

七、PSP

PSP2.1 任务内容 计划共完成需要的时间(min) 实际共完成需要的时间(min)
planning 计划 5 15
Estimate 估计这个任务需要多少时间,并规划大致步骤 10 5
Development 开发 700 807
Analysis 需求分析(包括学习新技术) 30 60
Design Spec 生成设计文档 20 35
Design Review 设计复审(和同事核审设计文档) 5 7
Coding Standard 代码规范(为目前的开发制定合适的规范) 10 20
Design 具体设计 120 100
Coding 具体编码 120 240
Code Review 代码复审 50 40
Test 测试(自我测试,修改代码,提交修改) 100 120
Reporting 报告 60 100
Test Report 测试报告 30 20
Size Measurement 计算工作量 10 15
Postmortem &Process
Improvement Plan
事后总结,并提出过程改进计划 20 30

八、经验分享;

​ 本次实验刚布置下来的时候我就感觉到了难度,可能跟自己前几个学期没有好哈学习有关,导致现在对贪心算法,回溯算法,动态规划算法不太熟悉和理解,花费了大量的时间来弄懂这个几个算法。我想之前的学习要是能够扎实一点,会比较好一点。

​ 在完成项目的过程中,我对项目的完成也有了自己的计划,我发现有一个比较好的计划,是很重要的,不能随便像无头的苍蝇一样乱来,有条不紊才能加快项目完成的进度以及效率。

​ 多尝试着自己写代码,可以百度一下,但不要照搬照抄,可以对别人的方法进行采纳。不尝试自己写代码,是永远不会写代码的。

​ 在写代码的时候,才发现自己好多语法的细节并不理解,只知道大概,并没有深入学习,导致一知半解。所以在学习的时候还是得注重细节,注重基础。基础牢靠才能越走越高。

任务四(项目提交):

posted @ 2022-03-22 00:58  丸子头野鸽儿  阅读(74)  评论(2编辑  收藏  举报