201871030106-陈鑫莲 实验二 个人项目-《D{0-1} KP 问题》项目报告

项目 内容
课程班级博客链接 班级博客
这个作业要求链接 作业要求
我的课程学习目标 1.掌握软件项目个人开发流程
2.掌握Github发布软件项目的操作方法
这个作业在哪些方面帮助我实现学习目标 1.熟悉并掌握GitHub与Eclipse的连接
2.熟悉java语言的开发步骤
3.进一步加深对折扣{0-1}问题的动态规划和回溯算法
4.熟悉使用java语言对文件的读取与导出
项目GitHub的仓库链接地址 仓库链接

1、实验目的与要求

(1)掌握软件项目个人开发流程。
(2)掌握GitHub发布软件项目的操作方法。

2、实验内容与步骤

任务1:

      已认真点评班级博客中“常用源代码管理工具与开发工具”作业。链接如下:
点评1,具体如图1:

图1

点评2,具体如图2:

图2

点评3,具体如图3:

图3

点评4,具体如图4:

图4

点评5,具体如图5:

图5

点评6,具体如图6:

图6

任务2:

      我读完《构建之法》后,对PSP的理解如下:
   PSP(Personal Software Process),个人软件开发流程的任务清单如下表所示:

PSP 任务内容
Planning
    - Estimate
Development
    - Analysis
    - Design Spec
    - Design Review
    - Coding Standard
    - Design
    - Coding
    - Code Review
    - Test
Record TimeSpent
Test Report
Size Measurement
Postmortem
Process Improvement Plan
计划
    - 估计这个任务需要多少时间
开发
    - 分析需求
    - 生成设计文档
    - 设计复审(和同事审核设计文档)
    - 代码规范(为目前的开发制定合适的规范)
    - 具体设计
    - 具体编码
    - 代码复审
    - 测试(包括自测,修改代码,提交修改)
记录用时
测试报告
计算工作量
事后总结
提出过程改进计划

任务3:

1.需求分析
      背包问题(Knapsack Problem,KP)是NP Complete问题,也是一个经典的组合优化问题,有着广泛而重要的应用背景。{0-1}背包问题({0-1 }Knapsack Problem,{0-1}KP)是最基本的KP问题形式,在此之前,学习过{0-1}背包问题的动态规划算法以及回溯法,本实验中任务3-1要求读取所给TXT文件的有效D{0-1}KP数据,任务3-1是将其读取的有效数据以重量为横轴、价值为纵轴的数据散点图,任务3-3要求对一组D{0-1}KP数据按项集第三项的价值:重量比进行非递增排序,即递减排序,任务3-4是选择动态规划算法、回溯算法求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位),任务3-5是将任务3-4中计算所得最优解、求解时间和解向量可保存为txt文件或导出EXCEL文件

2.功能设计
- 基本功能:
   (1)可正确读入实验数据文件的有效D{0-1}KP数据;
   (2)能够绘制任意一组D{0-1}KP数据以重量为横轴、价值为纵轴的数据散点图;
   (3)能够对一组D{0-1}KP数据按项集第三项的价值:重量比进行非递增排序;
   (4)用户能够自主选择动态规划算法、回溯算法求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位);
   (5)任意一组D{0-1} KP数据的最优解、求解时间和解向量可保存为txt文件或导出EXCEL文件。

3.设计实现
   (1)ReadTheFil类 :通过文件路径来创建文件实例,把FileInputStream实例 传递到 BufferedInputStream,目的是能快速读取文件,最后,使用available检查是不是读到了文件末尾。
   (2)ScatterDiagram类 :创建二维数组data存储profit价值和height重量,以重量为横轴、价值为纵轴,建立直角坐标系画出散点图。
   (3)WeightRatio类 :分别定义int类型数组profit和weight数组将价值和重量存储,因为所给数据全部为int型,再定义比值ratio为double类型,再将其int类型数组强制转换为double进行比值运算,最后运用冒泡排序将比值进行降序排序。
   (4)Time类 :使用动态规划算法:在0/1背包问题中,物品i或者被装入背包,或者不被装入背包,设xi表示物品i装入背包的情况,则当xi=0时,表示物品i没有被装入背包,xi=1时,表示物品i被装入背包。

4.测试运行

   

   (1)读入有效数据,如图7:

图7

   

   (2)绘制散点图,如图8:

图8

   

   (3)重量比排序,如图9:

图9

   

   (4)计算最优解及求解时间,如图10:

图10

   

   (5)保存为txt文件,如图11:


图11

5.代码片段

   (1)读入实验数据文件的有效D{0-1}KP数据:

try{
        //第一步 通过文件路径来创建文件实例
        fis = new FileInputStream(file);
        /*把FileInputStream实例 传递到 BufferedInputStream
                 目的是能快速读取文件
         */
        bis = new BufferedInputStream(fis);
        /*available检查是不是读到了文件末尾 */
        
        while( bis.available() > 0 ){                 
            System.out.print((char)bis.read());
        }
        
     }catch(FileNotFoundException fnfe)
      {
          System.out.println("文件不存在" + fnfe);
      }

      catch(IOException ioe)
      {
          System.out.println("I/O 错误: " + ioe); 
      }

   

   (2)绘制散点图:

int h = getHeight();//重量
	int w = getWidth();	//价值

	// 横坐标	
	g2.draw(new Line2D.Double(PAD, w-PAD, h-PAD, w-PAD));
	// 纵坐标
	g2.draw(new Line2D.Double(PAD, PAD, PAD, w-PAD));
	
	
	double xInc = (double)(w - 2*PAD)/(data.length-1);
	double scale = (double)(h - 2*PAD)/getMax();
	
	// 数据点(坐标)	
	g2.setPaint(Color.blue);//点的颜色
	
	for(int i = 0; i < data.length; i++) {
	double x = PAD + i*xInc;	
	double y = h - PAD - scale*data[i];	
	g2.fill(new Ellipse2D.Double(x-2, y-2, 4, 4));	

   

   (3)重量比排序:

//冒泡排序
		double tmp;
		for (int a= 1; a < ratio.length; a++) {
			for (int j = 0; j < ratio.length-1; j++) {
				if(ratio[j] < ratio[j+1]){
					tmp = ratio[j];
					ratio[j] = ratio[j+1];
					ratio[j+1] = tmp;
				}
			}


   

   (4)计算最优解及求解时间:

//1.创建二维数组
        //v[i][j]表示在前i个物品中能够装入容量为j的背包中的最大价值
        int[][] v=new int[n+1][m+1];
        //存放记录数组
        int[][] path=new int[n+1][m+1];

        //2.初始化第一行第一列(已经处理了,因为默认是0)
        //3.根据公式来动态规划处理
        for (int i = 1; i < v.length; i++) {
            for (int j = 1; j < v[0].length; j++) {
                //公式
                if(w[i-1]>j){//因为我们程序i是从1开始的,因此原来的公式中的w[i]修改成w[i-1]
                    v[i][j]=v[i-1][j];
                }else{
                    //v[i][j]=Math.max(v[i-1][j],val[i-1]+v[i-1][j-w[i-1]]);
                    if(v[i-1][j]<val[i-1]+v[i-1][j-w[i-1]]){
                        v[i][j]=val[i-1]+v[i-1][j-w[i-1]];
                        path[i][j]=1;
                    }else{
                        v[i][j]=v[i-1][j];
                    }
                }
            }
        }

6.总结

       刚拿到题目时,真的感觉这次实验非常难,而且还要使用GitHub创建仓库来与Eclipse相连接,又为这个作业增添了不少难度,因为我本身动手能力就较弱。在本次实验的具体实行过程中,我又熟悉重温了一遍Eclipse集成开发环境的项目搭建与运行,这次实验要求较多且很有难度,因为实验要求需要将Eclipse中的代码传到GitHub中,因此,必须要熟悉并掌握GitHub与Eclipse的连接,在连接的过程中遇到了很多困难,比如在最后一步时系统总是提示Eclipse无法连接github,尝试了很多方法,比如修改打开Eclipse安装目录下的eclipse.ini添加一句:“-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2 ”,虽然我没有深刻理解这一步的作用,我添加好之后,系统还是提示不能连接,找了很多参考资料,在最后终于找到了一篇文章,解决了我很大一部分问题,这篇

文章

给了我很多的提示与帮助。


"模块化"原则:

  1. 单一职责原则:

    类的职能要单一:

    遵循单一职责原则。分别建立两个类T1、T2,使T1完成职责P1功能,T2完成职责P2功能。这样,当修改类T1时,不会使职责P2发生故障风险;同理,当修改T2时,也不会使职责P1发生故障风险
  2. 里氏替换原则:

    子类对象可以替换父类对象。子类不要增加父类没有的约束。这样会导致父类有些方法不能用。从而不能真正的实现 : 子类对象可以替换父类对象,如果子类重写了父类已实现的方法,那么子类调用的父类的方法就完全没用了,从而不是真正意义上的继承。
  3. 依赖倒置原则:

    高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。

    4.接口隔离原则:

    在设计接口的时候,给每一个接口设计不多不少的方法,因为,如果设计的方法多了,当某个类通过接口来依赖某个类的时候,被依赖的那个类要实现的方法太多了,会造成那个类中大量的代码冗余,不可过少的原因是,接口太多,会让设计变复杂,且不便于管理。

    5.迪米特原则:

    低耦合,高内聚,即类A与类B,如果没必要依赖吗,则代码尽量不要耦合,如果这两个类要产生通信,则创建一个中间的通信类C去与这两个类进行交互。但是这样的通信类要适量。

    6.开闭原则:

    对实现封闭,对扩展开放。即当一个一个方法需要增加其他的功能,或者代码需要重构的时候,要扩展软件的行为,尽量不要去修改已有的代码。用抽象构建框架,方法的实现来扩展细节。

(该内容参考于:参考资料

      其中,我在进行本次实验时,实现软件设计“模块化”原则,即单一职责原则、依赖倒置原则和开闭原则。

7.PSP展示

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

小结:

       在本次实验中,我花费时间最长的就是具体编码部分,虽然之前也学习过JAVA语言,但是因为太久没有写过java程序,且很久没有复习具体的编程,导致我忘记了很多具体的细节,因此本次实验在这部分花费时间较长,而且在进行代码测试时,有时候会有很多bug,一时半会儿改不好,也花费了很多时间,但是好在java有写问题可以自动修改。而且我在制做PSP表格时,计划的时间过短,而实际使用时间过长,使两者之间的差距过大。在今后的实验过程中,我将会加强自己的编程能力,多写代码,强加练习,在平时的生活学习中勤加思考,在小组合作学习中也要多多思考,长善救失,取长补短。

任务4:

      

已完成任务3的程序开发,并将项目源码的完整工程文件提交到已注册Github账号的项目仓库中。


      

GitHub账户仓库的创建流程如下图所示:

第一步:点击新建仓库,如图12:

图12

第二步:填写相关信息,如图13:

图13

第三步:Eclipse中显示连接成功并显示GitHub仓库链接,如图14:

图14

第四步:GitHub中显示相关代码,如图15:

图15
posted on 2021-03-31 09:51  陈鑫莲  阅读(281)  评论(1编辑  收藏  举报