201871030102-崔红梅 实验二 个人项目—— D{0-1}KP 项目报告

项目 内容
课程班级博客链接 班级博客
这个作业要求链接 实验二作业链接
我的课程学习目标 1、熟练掌握将本地代码保存至GitHub中
2、掌握折扣背包问题
3、回顾动态规划算法和回溯算法
4、对java语言进行熟练应用
这个作业在哪些方面帮助我实现学习目标 1、同学之间的相互解答
2、网上相关知识的查询
3、上学期的算法课程是的我对动态规划算法和回溯算法有一定的掌握
项目Github的仓库链接地址 Github的仓库链接地址

任务1:阅读教师博客中已提交相关至少3份作业

  • 已经对本班三位同学的博客认真进行评价。

任务2:详细阅读《构建之法》第1章、第2章,掌握PSP流程

  • 已经阅读了《构建之法》的第一章与第二章,并且掌握了PSP流程。

任务3:背包问题

1、需求分析

从若干具有价值系数与重量系数的物品(或项)中,选择若干个装入一个具有载重限制的背包,并使装入物品的重量系数之和在不超过背包载重前提下价值系数之和达到最大。

2、功能设计

1、可读取实验数据,有效呈现所有数据;

2、用读取的数据绘制出以重量为横轴、价值为纵轴的数据散点图;

3、将数据按项集第三项的价值:重量比进行非递增排序;

4、用户能够自主选择动态规划算法、回溯算法求解数据的最优解和求解时间;

5、数据的最优解、求解时间和解向量可保存为txt文件

3、设计实现
可正确读入实验数据文件的有效D{0-1}KP数据;

用字符串的包含关系来切割数据,将价值和重分别放在二维数组中,将背包的容量放在一个一维数组中。

能够绘制任意一组D{0-1}KP数据以重量为横轴、价值为纵轴的数据散点图;

创建一个窗口来显示面板,绘制x轴和y轴,将二维数组中的数据传过来,让其对应的点显示在面板上。

能够对一组D{0-1}KP数据按项集第三项的价值:重量比进行非递增排序;

设置一个类item,其中包含两个变量(价值和重量),再创建一个item类型的ArrayList的列表,用来存放每一组的数据项,再创建一个sortList类,包含每一个数据项(List data)和每一个数据项的第三项的价值/重量(Float rate),最后创建一个sortList类型的ArrayList的列表,将数据存放进去以后,按照第三项的价值/重量(Float rate)来对每一个数据项集进行排序,排好序后输出。

用户能够自主选择动态规划算法、回溯算法求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位);

通过不同的选择,选择是动态规划算法还是回溯算法,解得背包获得的最大价值,将加入背包的物品存放在数组中,通过开始时间和结束时间的差求得求解时间,将其保存即可。

任意一组D{0-1} KP数据的最优解、求解时间和解向量可保存为txt文件或导出EXCEL文件。

将上一步获取的最优解、求解时间等写进文件中。

4、测试运行

1、任选一个文件,对该文件任选一组数据:





2、首先,将数据分割出来








3、绘制任意一组数据的散点图





4、提升了编码的可读性,可通过选择来进行执行不同的任务:





5、对一组数据按项集第三项的价值:重量比进行非递增排序





6、动态规划算法求解





7、将结果写入文件





5、代码展示

1、读取数据:

  private static void readFile() throws IOException {
        String rootPath="E:\\idea_workspace\\data\\idkp1-10.txt";
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入文件名 (1、idkp1-10;  2、sdkp1-10;  3、udkp1-10;  4、wdkp1-10)");
        int fileName=scanner.nextInt();
        switch (fileName){
            case 1:
                rootPath="E:\\idea_workspace\\data\\idkp1-10.txt";
                break;
            case 2:
                rootPath="E:\\idea_workspace\\data\\sdkp1-10.txt";
                break;
            case 3:
                rootPath="E:\\idea_workspace\\data\\udkp1-10.txt";
                break;
            case 4:
                rootPath="E:\\idea_workspace\\data\\wdkp1-10.txt";
                break;
        }
        //BufferedReader是可以按行读取文件
        FileInputStream inputStream = new FileInputStream(rootPath);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String str = null;
        //读取文件中的一行数据

        //存放物品价值和质量的列表
        ArrayList<String> profitList = new ArrayList<>();
        ArrayList<String> weightList = new ArrayList<>();
        String[] cubage = new String[12];
        int packnum=0;
        while((str = bufferedReader.readLine()) != null)
        {
            if(str.contains("cubage of knapsack")){
                String replace = str.replace(".", "");
                String[] s = replace.split(" ");
                cubage[packnum]=s[s.length-1];
                //System.out.println("==========请输出背包的容量:"+cubage[packnum]);
                packnum++;
            }
            if(str.contains("The profit of")){
                profitList.add(bufferedReader.readLine());
            }
            if(str.contains("The weight of")){
                weightList.add(bufferedReader.readLine());
            }
        }
        //遍历物品重量,将其分割出来
        //System.out.println("输出所有物品价值:");
        int i=0,j=0;
        for (String s : profitList) {
            j=0;
            String replace = s.replace(".", "");
            String[] split = replace.split(",");
            for (String s1 : split) {
                //字符型转整形
                profits[i][j] =  Integer.parseInt(s1);
                //System.out.println("输出第"+i+"组第"+j+"个物品的价值:"+profits[i][j]);
                j++;
            }
            i++;
        }
        //遍历物品重量,将其分割出来
        //System.out.println("\n输出所有物品重量:\n");
        int m=0,n;
        for (String s : weightList) {
            n=0;
            String replace = s.replace(".", "");
            String[] split = replace.split(",");
            for (String s1 : split){
                //字符型转整形
                weights[m][n] = Integer.parseInt(s1);
                //System.out.println("输出第"+m+"组第"+n+"个物品的重量:"+weights[m][n]);
                n++;
            }
            m++;
        }
    }

2、排序:

private static void dataOrder(Scanner scanner) {
        System.out.println("输入将要排序的组数:");
        int group=scanner.nextInt();
        List<item> items = new ArrayList<>();
        for (int i1 = 0; i1 < profits[group - 1].length; i1++) {
            if(profits[group - 1][i1]!=0){
                item item = new item();
                item.setProfit(profits[group - 1][i1]);
                item.setWeight(weights[group - 1][i1]);
                items.add(item);
            }
        }
        ArrayList<sortList> sortLists = new ArrayList<>();
        for (int k = 0; k < items.size(); k=k+3) {
            List<item> items1 = items.subList(k, k + 3);
            sortList sortList = new sortList();
            sortList.setData(items1);
            item item = items1.get(items1.size() - 1);
            float v = item.getProfit() / new Float(item.getWeight());
            sortList.setRate(v);
            sortLists.add(sortList);
        }

        Collections.sort(sortLists);
        for (sortList sortList : sortLists) {
            System.out.println(sortList.toString());
        }
    }

3、将结果写入文件

private static void write(int results,double time) throws IOException {
        File file =new File("E:\\idea_workspace\\data\\result.txt");
        Writer out =new FileWriter(file);
        String data="888";
        out.write("得到背包的最大价值为: "+results);
        out.write("      程序运行时间: "+time);
        out.close();
    }
6、总结我所设计的程序如何实现软件设计“模块化”原则

1、单一职责原则

就是函数和数据的功能单一,这样便于模块化,也能让模块变得更加内聚

2、开闭原则

用增加新的代码来进行扩展我们模块的功能,而不是修改当前的代码来兼容以前的代码,防止破坏当前代码功能。

3、替换原则

其主要是为了不改变底层的变动的一种思想,当我们上层需要实现新的功能的时候,我们底层的接口一般不需要进行修改,而是用现有接口实现新的上层应用,其实也就要求我们在进行底层接口开发的时候,中层接口也应该具备底层接口的相关功能,以便上层使用。

7、我的PSP展示
任务内容 计划共完成需要的时间/分钟 实际完成需要的时间/分钟
计划总时长 950 2110
任务一 30 25
评价三位同学博客 30 25
任务二 60 60
阅读《构建之法》第1章、第2章,掌握PSP流程 60 60
任务三 860 2025
需求分析 10 10
功能分析 20 20
设计实现 50 60
学习读取文件数据 20 30
编写代码实现数据读取 40 125
学习C语言绘制散点图 50 110
编写代码实现散点图的绘制 60 200
实现对数据按性价比进行排序 40 100
学习动态规划算法 60 120
学习回溯算法 40 120
编写代码实现0/1背包问题动态规划算法 80 280
编写代码实现0/1背包问题回溯算法 80 270
将数据的最优解、求解时间和解向量可保存为txt文件 90 260
代码测试 100 110
编写博客 120 100

在编写代码这部分出入较大,关键是因为代码中的bug太多,再修改过程中花费了较多时间,很多需要从网上找原因,请同学帮忙。
归根结底,还是经验不足,能力有待提升,对java等语言掌握的也不好。

4、实验总结

  • 通过本次作业,我了解到了制定PSP的重要性,对自己的时间进行合理的规划,尽量在规定的时间内完成自己的项目,这对一个编程人员来说是至关重要的。
  • 本次作业反应了我的编程水平,还需提高。
  • 本次个人项目中我意识到了团队的重要性,我们本次只写了运行,没有加用户交互界面,但这对我们来说都耗费了不少时间,可见要是一个团队,一人负责一个模块,效率肯定很高。

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

  • 已将项目源码的完整工程文件提交到我所注册的Github账号的项目仓库中。


posted @ 2021-03-19 10:17  樱柯  阅读(283)  评论(1编辑  收藏  举报