201971010241-王晨阳 实验二 个人项目《{0-1}KP问题》项目报告
201971010241-王晨阳 实验二 个人项目《{0-1}KP问题》项目报告
项目 | 内容 |
---|---|
课程班级博客链接 | 2019级卓越班 |
这个作业要求链接 | 软件工程个人项目 |
我的课程学习目标 | (1)掌握软件项目个人开发流程; (2)掌握Github发布软件项目的操作方法。 |
这个作业在哪些方面帮助我实现学习目标 | (1)详细阅读《构建之法》第1章、第2章,掌握PSP流程; (2)复习背包问题相关算法知识; (3)将项目源码的完整工程文件提交到Github账号的项目仓库中. |
项目Github的仓库链接地址 | 小王的实验二 |
实验内容
任务1:阅读教师博客“常用源代码管理工具与开发工具”内容要求,点评班级博客中已提交相关至少3份作业
评论地址 | 评论内容 |
---|---|
201971010157-张颖 实验一 软件工程准备-带着问题学习软件工程 | 你的博客内容非常充实,对任务要求完成的十分不错,排版逻辑清晰,让读者很容易就清楚你表达的内容,值得点赞学习 |
201971010160-谢家俊 实验一 软件工程准备—初识软件工程 | 博主的博客好看的背景是第一大亮点,内容十分详细,阅读也不会有压迫感,总的来说,博主写这篇博客是十分用心的! |
201971010111-何晨泽 实验一 软件工程-从《现代软件工程-构建之法》对软件工程进行初步认识 | 何同学的博客一经阅读就给人赏心悦目的感觉,排版整齐、大方简洁;提出的问题也值得我们深思 |
任务2:详细阅读《构建之法》第1章、第2章,掌握PSP流程
-
软件开发流程
软件工程包括了开发,运营, 维护软件的过程中有很多技术, 做法, 习惯, 和思想。软件工程把这些相关的技术和过程统一到一个体系中, 叫 “软件开发流程”,软件开发流程的目的是为了提高软件开发, 运营, 维护的效率,以及用户满意度, 可靠性,和软件的可维护性。
-
PSP的特点
- 不局限于某一种软件技术 (如编程语言), 而是着眼于软件开发的流程, 这样不同应用的工程师可以互相比较。
- 不依赖于考试, 而主要靠工程师自己收集数据, 然后统计提高。
- 在小型,初创的团队中, 高质量的项目需求很难找到,这意味着给程序员的输入质量不高,在这种情况下, 程序员的输出 (程序/软件) 往往质量不高, 然而这并不能全部由程序员负责。
- PSP 依赖于数据
- 需要工程师输入数据, 记录工程师的各项活动, 这本身就需要不小的代价。
- 如果数据不准确或有遗失, 怎么办? 让工程师编造一些?
- 如果一些数据不利于工程师本人 (例如: 花很多时间修改缺陷), 我们怎么能保证工程师能如实地记录这些数据呢?
- PSP的目的是记录工程师如何实现需求的效率, 而不是记录顾客对产品的满意度。工程师可能很高效地开发出一个顾客不喜欢的软件, 那这个工程师还是一个优秀的工程师么?
任务3:项目开发背景
背包问题(Knapsack Problem,KP)是NP Complete问题,也是一个经典的组合优化问题,有着广泛而重要的应用背景。{0-1}背包问题({0-1 }Knapsack Problem,{0-1}KP)是最基本的KP问题形式,它的一般描述为:从若干具有价值系数与重量系数的物品(或项)中,选择若干个装入一个具有载重限制的背包,如何选择才能使装入物品的重量系数之和在不超过背包载重前提下价值系数之和达到最大?
{0-1}KP数据集是研究{0-1}背包问题时,用于评测和观察设计算法性能的标准数据集;动态规划算法、回溯算法是求解{0-1}背包问题的经典算法。查阅相关资料,设计一个采用贪心算法、动态规划算法、回溯算法求解{0-1}背包问题的程序,程序基本功能要求如下:
1.可正确读入实验数据文件的有效{0-1}KP数据;
2.能够绘制任意一组{0-1}KP数据以价值重量为横轴、价值为纵轴的数据散点图;
3.能够对一组{0-1}KP数据按重量比进行非递增排序;
4.用户能够自主选择贪心算法、动态规划算法、回溯算法求解指定{0-1} KP数据的最优解和求解时间(以秒为单位);
5.任意一组{0-1} KP数据的最优解、求解时间和解向量可保存为txt文件或导出EXCEL文件。
任务4:完成任务3的程序开发,将项目源码的完整工程文件提交到你注册Github账号的项目仓库中。
1.需求分析
- 本次题目主要是通过贪心算法、动态规划算法和回溯算法来求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位),而0/1背包问题对于物品的选择只有两种:装入或者不装入背包。那么如何选择装入背包的物品,使得包中物品的总价值最大?我将举例使用动态规划算法分以下三步来实现:
- 划分子问题:将原问题分解为若干个子问题,每个子问题对应一个决策阶段,并且子问题之间具有重叠关系。
- 确定动态规划函数:根据子问题之间的重叠关系找到子问题满足的递推关系式(即动态规划函数),这是动态规划算法的关键。
- 填写表格:设计表格,以自底向上的方式计算各个子问题的解并填表,实现动态规划过程。
2.功能设计
(1)读取文件数据:可正确读入实验数据文件的有效D{0-1}KP数据;
(2)绘制散点图:绘制任意一组D{0-1}KP数据以重量为横轴、价值为纵轴的数据散点图;
(3)排序:对一组D{0-1}KP数据按项集第三项的价值:重量比进行非递增排序;
(4)求解最优解和时间:求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位);
(5)将数据结果保存为txt文件:将一组D{0-1} KP数据的最优解、求解时间和解向量保存为txt文件;
3.设计实现
-
贪心算法的基本思想
从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。当达到算法中的某一步不能再继续前进时,算法停止。
-
动态规划法的·基本思想
将大问题划分为小问题进行解决,从而一步步获取最优解的处理算法,先求解子问题,然后从这些子问题的解得到原问题的解(子问题往往不是相互独立的)。
-
回溯法的基本思想
从一条路往前走,能进则进,不能进则退回来,换一条路再试。回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题。
4.代码展示
排序函数:
void knapsack()
{
int i,j;
int temporder = 0;
double temp = 0.0;
for(i=1;i<=n;i++)
perp[i]=v[i]/w[i]; //计算单位价值(单位重量的物品价值)
for(i=1;i<=n-1;i++)
{
for(j=i+1;j<=n;j++)
if(perp[i]<perp[j])//冒泡排序perp[],order[],sortv[],sortw[]
{
temp = perp[i]; //冒泡对perp[]排序
perp[i]=perp[j];
perp[j]=temp;
temporder=order[i];//冒泡对order[]排序
order[i]=order[j];
order[j]=temporder;
temp = v[i];//冒泡对v[]排序
v[i]=v[j];
v[j]=temp;
temp=w[i];//冒泡对w[]排序
w[i]=w[j];
w[j]=temp;
}
}
}
回溯函数:
void backtrack(int i)
{ //i用来指示到达的层数(第几步,从0开始),同时也指示当前选择完成了几个物品
double bound(int i);
if(i>n) //递归结束的判定条件
{
bestp = cp;
return;
}
//如若左子节点可行,则直接搜索左子树;
//对于右子树,先计算上界函数,以判断是否将其减去
if(cw+w[i]<=c)//将物品i放入背包,搜索左子树
{
cw+=w[i];//同步更新当前背包的重量
cp+=v[i];//同步更新当前背包的总价值
put[i]=1;
backtrack(i+1);//深度搜索进入下一层
cw-=w[i];//回溯复原
cp-=v[i];//回溯复原
}
if(bound(i+1)>bestp)//如若符合条件则搜索右子树
backtrack(i+1);
}
5.测试运行
以第一组数据为例:
1.读入数据
2.运行算法并得出结果:
3.输出数据到txt文件
6.PSP展示及项目总结
PSP2.1 | 任务内容 | 计划共完成需要的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
Planning | 计划 | 1 | 0.8 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 1 | 0.8 |
Development | 开发 | 30 | 35 |
Analysis | 需求分析 | 5 | 5 |
Design Spec | 生成设计文档 | 2 | 2 |
Design Review | 设计复审 | 2 | 2 |
Design | 具体设计 | 15 | 20 |
Coding | 具体编码 | 2 | 2 |
Code Review | 代码复审 | 2 | 2 |
Test | 测试(自我测试、修改代码、提交修改) | 2 | 2 |
Reporting | 报告 | 3 | 5 |
Test Report | 测试报告 | 2 | 3 |
Size Measurement | 计算工作量 | 0.5 | 1 |
Postmortem&Process Imporvement Plan | 事后总结,并提出过程改进计划 | 0.5 | 1 |
- 项目总结:从来没有觉得{0,1}背包问题如此的难,通过实际与计划的对比我发现自己编码能力还有待欠缺,导致自己在具体编码过程中不仅慢,也出现了一写问题以至于还影响了自己测试的计划实际,因为自己要因为编码错误而不断修改测试,在这些方面使得我浪费了很多时间。结合整个作业过程,这个问题也有自己编码不规范没有“模块化”的习惯,使得所有功能在一个大程序里完成的因素。