201971010216-李斌-实验二 软件工程 个人项目 - 用所学知识解决0/1背包问题
软件工程个人项目
目的 | 内容 |
---|---|
班级 | 2019级卓越工程师班 |
作业 | 实验二 |
课程学习目标 | (1)掌握软件开发的基本流程;(2)掌握Github上传代码的基本流程; (3)掌握PSP流程。 |
学习目标实现 | (1)阅读教师博客“常用源代码管理工具与开发工具;(2)总结详细阅读《构建之法》第1章、第2章,掌握PSP流程; (3)完成任务3的程序开发,将项目源码的完整工程文件提交到你注册Github账号的项目仓库中 |
项目Github仓库链接 | 仓库 |
实验任务及其完成情况
任务1:阅读教师博客“常用源代码管理工具与开发工具
评论个数 | 评论地址 | 评论 |
---|---|---|
评论一 | 尚洁 | 这篇博客排版简单清楚,内容明确,任务条例清晰,内容充实,非常不错 |
评论二 | 高扬 | 博主写的很好,大大的拓展了我的知识,同时提高了我对于问题提问的方式及格局!内容清晰,必须顶一下!!!!!!! |
评论三 | 孙德弘 | 博主写的很好,大大的拓展了我的知识,同时提高了我对于问题提问的方式及格局!内容也比较简明!!!!!!! |
任务2:总结详细阅读《构建之法》第1章、第2章,掌握PSP流程
第一章:主要详细讲解了什么是软件工程
-
软件 = 程序 + 软件工程:
-
邹欣老师首先解释了什么是“软件”,什么是“程序”,为我们介绍了软件工程的概念。最后讲述了软件开发的不同阶段,引出了什么是软件工程这个问题。
-
软件工程的定义:
- 软件工程的特殊性:复杂性,不可见性,易变性,服从性,非连续性;
- 软件工程的知识领域、软件工程的三大类基础知识领域:计算基础,数学基础和工程基础;
- 软件工程的目标:用户满意度,可靠性,软件流程的质量,可维护性。
第二章:主要讲解了PSP(个人软件开发流程)
- 1 单元测试:单元测试是模块质量稳定和量化的保证。
- 2 回归测试:从正常工作的稳定状态退化到不正常工作的不稳定状态。单元测试是回归测试的基础。
- 3 效能分析工具:改进程序。
- 个人开发流程:(1)计划 (2)开发 (3)记录用时(4)测试报告(5)计算工作量(6)事后总结(7)提出过程改进计划。
-
PSP特点:
- 不局限于某一种软件技术,而是着眼于软件开发的流程。
- 不依赖于考试,而是依赖工程师自己收集数据,然后分析,提高。
- 依赖于数据
-
PSP作用:
- PSP可以帮助软件工程师在个人的基础上运用过程的原则,借助于PSP提供的一些度量和分析工具,了解自己的技能水平,控制和管理自己的工作方式,使自己日常工作的评估、计划和预测更加准确、更加有效,进而改进个人的工作表现,提高个人的工作质量和产量,积极而有效地参与高级管理人员和过程人员推动的组织范围的软件工程过程改进。
任务3:项目开发
1. 项目内容:
- 背包问题(Knapsack Problem,KP)是NP Complete问题,也是一个经典的组合优化问题,有着广泛而重要的应用背景。{0-1}背包问题({0-1 }Knapsack Problem,{0-1}KP)是最基本的KP问题形式,它的一般描述为:从若干具有价值系数与重量系数的物品(或项)中,选择若干个装入一个具有载重限制的背包,如何选择才能使装入物品的重量系数之和在不超过背包载重前提下价值系数之和达到最大?
2.需求分析
- 主要有以下功能模块
- 1.读入实验数据文件:正确读入实验数据文件的有效{0-1}KP数据,并将其处理为便于后续操作的数据形式。
- 2.散点图绘制:绘制任意一组{0-1}KP数据以价值重量为横轴、价值为纵轴的数据散点图。
- 3.排序:给导入的数据进行排序,排序按的单位质量的价值进行排序。
- 4.贪心算法:采用贪心算法求解不超过背包容量的最大价值和解。利用的当前最优的原理,解不一定是最优解
- 5.动态规划算法:采用动态规划算法求解不超过背包容量的最大价值。利用递推函数的方法,建立数学模型求解,一定是最优解
- 6.回溯算法:采用回溯算法求解不超过背包容量的最大价值。可以得到最优解。
- 7.结果显示:得到的实验结果通过弹窗进行显示。
3.功能设计
- 通过上面的需求分析,代码主要由七个部分构成
4.关键函数
- 1.贪心算法代码
```
void knap_m()
{
for (int i=0;i<=n;i++)
{
NodeType_Knap k;
k.w = w[i];
k.v = v[i];
A.push_back(k);
}
for (int i=1;i<=n;i++) //求v/w
A[i].p=A[i].v/A[i].w;
sort(++A.begin(),A.end()); //A[1..n]排序
Knap();
}
```
贪心算法是一种只考虑当前最优的算法,其不从总体上考虑,所以贪心算法不是对所有问题都能求得整体最优解,像本实验中的0-1背包问题,用贪心算法一般求得的是局部最优解,用贪心算法解0-1背包问题原理如下:
首先我们按照物品的单位重量价值来进行排序,然后按照单位重量价值从高到低依次进行选择,若其能装入背包则将其装入,不能则继续判断下一个直至所有物品都判断完,就得到了问题的一个解。但是对于0-1背包问题,用贪心算法并不能保证最终可以将背包装满,部分剩余的空间使得单位重量背包空间的价值降低了,这也是用贪心算法一般无法求得0-1背包最优解的原因。
- 2. 动态规划法
动态规划基本思想是将带求解的问题分解成若干子问题,先求解子问题,再结合这些子问题的解得到原问题的解。
用动态规划算法解0-1背包原理为:设0-1背包问题的子问题
max∑vkxk,(k=i-n) ∑wkxk<=j
xk∈{0,1} i<=k<=n
的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,···,n时0-1背包问题的最优值,由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下:
m(i,j)= max{m(i+1,j),m(i+1,j-wi+vi)} j>=wi
m(i+1,j) 0<=j<=wn
m(n,j)= vn j>=wn
0<=j<wn
所以基于以上讨论,当wi(1<=i<=n)为正整数时,用二维数组m[][]来存储m(i,j)的值,最后m[1][c]给出所要求的0-1背包的最优值,相应的最优解有Traceback函数计算如下:如果m[1][c]=m[2][c],则x1=0,否则x1=1。当x1=0时,由m[2][c]继续构造最优解。当x1=1时,由m[2][c-w1]继续构造最优解。以此类推,可构造出相应的最优解(x1,x2,···xn)。
- 3.回溯法
是一种非常有效的方法,有“通用的解题法”之称。它有点像穷举法,但是更带有跳跃性和系统性,他可以系统性的搜索一个问题的所有的解和任一解。回溯法采用的是深度优先策略。
回溯法按深度优先策略搜索问题的解空间树。首先从根节点出发搜索解空间树,当算法搜索至解空间树的某一节点时,先利用剪枝函数判断该节点是否可行(即能得到问题的解)。如果不可行,则跳过对该节点为根的子树的搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先策略搜索。
三个步骤:
针对所给问题,定义问题的解空间;
确定易于搜索的解空间结构;
以深度优先的方式搜索解空间。
优化方法:
搜索过程使用剪枝函数来为了避免无效的搜索。剪枝函数包括两类:
使用约束函数,剪去不满足约束条件的路径;
使用限界函数,剪去不能得到最优解的路径。
解空间树分为两种:子集树和排列树。两种在算法结构和思路上大体相同。
所给的问题是从n个元素的集合S中找出满足某种性质的子集时,相应的解空间成为子集树。
如0-1背包问题,从所给重量、价值不同的物品中挑选几个物品放入背包,使得在满足背包不超重的情况下,背包内物品价值最大。它的解空间就是一个典型的子集树。
- 5.测试运行
用的软件是codebllok,所以文件可以倒进来,但是测试的时候需要自己输入,三种算法都在代码当中。
- 6.展示PSP
PSP2.1 | 任务内容 | 计划完成所需要的时间 | 实际完成所需要的时间 |
---|---|---|---|
Planing | 计划 | 30 | 20 |
Estimate | 估计这个任务需要多少时间,并且规划大体步骤 | 10 | 20 |
Development | 开发 | 800 | 1200 |
Analysis | 需求分析 | 10 | 10 |
Designc Spec | 设计复审(和同事审核设计文档) | 5 | 20 |
Design Review | 生成设计文档 | 10 | 10 |
Coding Standard | 代码规范 | 5 | 5 |
Design | 具体设计 | 40 | 50 |
Coding | 具体编码 | 400 | 500 |
Code Review | 代码复查 | 50 | 50 |
Test | 测试(自我测试、修改代码、提交修改) | 20 | 30 |
REporting | 报告 | 200 | 300 |
Test Report | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 10 | 5 |
Postmorter&Process lmorovement Plan | 事后总结、并提出改进过程改进计划 | 10 | 30 |
任务四:完成任务3的程序开发,将项目源码的完整工程文件提交到你注册Github账号的项目仓库中。
进入网站后先新建一个仓库,然后导入,过程如下:
实验总结
- 本次实验差不多一共写了有两周的时间,实验中也遇到很多的问题,前两个任务相对而言比较简单吧,第一个任务是给三个以上的同学的博客进行评论,我差不多评论了有六条,但是我找了三条的链接放到了我的博客当中,第一个任务完成;第二个任务是看邹欣老师的软件工程-构建之法,主要是看第一、二章的内容,邹老师擅长于用例子来阐明一个问题,内容生动形象,能够很好的去理解,任务也全部完成了,任务三是解决0/1背包问题,主要使用的是三个算法(贪心、回溯、动态规划),第二部分单位质量非递增排序,第三部分文件输入数据,输出数据结果,这几个单独的部分在实验当中但是顺利完成了,但是整合到一起回溯有巨大的问题,散点图的相关C++代码也有问题,无法显示,任务大部分是顺利完成了,任务四把任务三的文件上传到github平台的仓库,因为是第一次使用这个代码托管平台,经过三次也是完成了要求,使用总体要求差不多都完成,但是实验代码还需要我以后不断的改进。
课题感悟
- 通过本次大型项目,第一次把之前所学零零散散的东西结合在一起,里面用到数据结构、算法设计与分析还有C和C++的相关知识,深刻的感觉到了软件工程的重要行,就像是水泥在房屋建造过程一样,把所学真正的结合起来,给我们受益匪浅,在以后软件项目开发积累了宝贵的经验,这也是单人完成的项目,再写博客的过程中之前的学习也有深刻的总结,通过这次实验学到了很多很多。