近似装箱问题

  • 解决装箱问题(bin packing problem)的算法。也可以用贪婪算法来完成

  • 给定N项物品,大小为s1,s2,s3…sn,所有的大小满足0 < si < 1。问题是要把这些物品装到最小数目的箱子中,已知每一个箱子容量是1个单位。我们用如下案例,有大小如下的物品:0.2, 0.5, 0.4, 0.7, 0.1, 0.3, 0.8的一列物品最优装修办法

  • 有两种结局方案:

    • 一种联机装箱问题(online bin packing problem)。在这种问题中,每一件物品必须放入一个箱子之后才能处理下一个物品
    • 第二中脱机装箱问题(offline bin packing problem)。在一个脱机装箱算法中,我们做任何事情都需要等所有的输入数据全被读取之后才进行
联机算法
下项合适算法
  • 算法定义:当处理任何一项物品,我们检查看他是否能装进去刚才放入物品的箱子中。 如果能,那么放入该箱子,否则,开辟一个新的箱子。

  • 算法实现简单,而且还是线性时间下运行

  • 算法实现:

/*** 近似装箱问题 - 联机算法 - 脱机算法** @author liaojiamin* @Date:Created in 14:12 2021/1/15*/
public class KnapsackProblem {private static final int MAX_WEIGHT = 10;/*** 随机生成10 以内的物品数据*/public static int[] getSource(int num) {int[] source = new int[num];Random random = new Random();for (int i = 0; i < num; i++) {source[i] = random.nextInt(10);System.out.println(source[i]);}return source;}/*** 下项适合算法:* 当处理任何一项物品适合,我们坚持是否能装进去刚才装物品的同一个箱子* 如果能,就放入,如果不能就重新开一个新箱*/public static int[][] multiKnasack(int[] source ) {int num = source.length;//极端情况,所有获取都是1 ,都在第一个里面int[][] myPackage = new int[num][num];int[] position = new int[num];int[] weight = new int[num];int packagePosition = 0;for (int i = 0; i < source.length; i++) {if (MAX_WEIGHT - weight[packagePosition] < source[i]) {packagePosition++;}myPackage[packagePosition][position[packagePosition]] = source[i];weight[packagePosition] += source[i];position[packagePosition] += 1;}return myPackage;}public static void main(String[] args) {int[] source = getSource(20);int[][] myPackage = multiKnasack(source);for (int i = 0; i < myPackage.length; i++) {System.out.print("第" + i + "个箱子:");for (int i1 = 0; i1 < myPackage[i].length; i1++) {if (myPackage[i][i1] > 0) {System.out.print(myPackage[i][i1] + ", ");}}System.out.println();}}
}
  • 下项合适算法有一个合理的性能保证,但是效果在实践中很差,因为在不需要开普新箱子的时候他却会开辟一个新的箱子。
首次合适算法
  • 算法定义:有序扫描箱子,并把新的物品放入足够能放下他的第一个箱子中。因此只有当前面那些放置物品的箱子已经容纳不下当前物品的时候才会开辟新的箱子
  • 算法实现:
/*** 近似装箱问题 - 联机算法 - 脱机算法** @author liaojiamin* @Date:Created in 14:12 2021/1/15*/
public class KnapsackProblem {private static final int MAX_WEIGHT = 10;/*** 随机生成10 以内的物品数据*/public static int[] getSource(int num) {int[] source = new int[num];Random random = new Random();for (int i = 0; i < num; i++) {source[i] = random.nextInt(10);System.out.println(source[i]);}return source;}/*** 首次适合算法:* 义序草庙箱子,并把新的一项物品放入能容纳的箱子中* */public static int[][] multiKnasackFirst(int[] source ){int num = source.length;int[][] myPackage = new int[num][num];int[] position = new int[num];int[] weight = new int[num];int packagePosition = 0;for (int i = 0; i < source.length; i++) {boolean isInsert = false;for (int j = 0; j < weight.length; j++) {if(MAX_WEIGHT - weight[j] >= source[i]){isInsert = true;myPackage[j][position[j]] = source[i];weight[j] += source[i];position[j] += 1;break;}}if(!isInsert){packagePosition ++;myPackage[packagePosition][position[packagePosition]] = source[i];weight[packagePosition] += source[i];position[packagePosition] += 1;}}return myPackage;}public static void main(String[] args) {int[] source = getSource(20);int[][] myPackage = multiKnasackFirst(source);for (int i = 0; i < myPackage.length; i++) {System.out.print("第" + i + "个箱子:");for (int i1 = 0; i1 < myPackage[i].length; i1++) {if (myPackage[i][i1] > 0) {System.out.print(myPackage[i][i1] + ", ");}}System.out.println();}}
}
  • 首次合适算法时间复杂度达到O(N^2),
最佳适合算法
  • 第三种策略最佳适合装箱法。改算法不是把一项物品放入所发现的第一个能容纳他的箱子,而是放到所有箱子中能容纳他的最满的哪一个箱子中。典型的方法。

  • 算法实现:

package com.ljm.resource.math.greedy;import java.util.Random;/*** 近似装箱问题 - 联机算法 - 脱机算法** @author liaojiamin* @Date:Created in 14:12 2021/1/15*/
public class KnapsackProblem {private static final int MAX_WEIGHT = 10;/*** 随机生成10 以内的物品数据*/public static int[] getSource(int num) {int[] source = new int[num];Random random = new Random();for (int i = 0; i < num; i++) {source[i] = random.nextInt(10);System.out.println(source[i]);}return source;}/*** 最佳合适算法* 将物品放入一个能容纳他并且最满的箱子中* */public static int[][] multiKnasackBest(int[] source ){int num = source.length;int[][] myPackage = new int[num][num];int[] position = new int[num];int[] weight = new int[num];int packagePosition = 0;for (int i = 0; i < source.length; i++) {int maxWeight = -1;int maxWeightId = -1;for (int j = 0; j <= packagePosition; j++) {if(MAX_WEIGHT - weight[j] > source[i]){if(weight[j] > maxWeight){maxWeight = weight[j];maxWeightId = j;}}}if(maxWeightId < 0){packagePosition++;myPackage[packagePosition][position[packagePosition]] = source[i];weight[packagePosition] += source[i];position[packagePosition] += 1;}else {myPackage[maxWeightId][position[maxWeightId]] = source[i];weight[maxWeightId] += source[i];position[maxWeightId] += 1;}}return myPackage;}public static void main(String[] args) {int[] source = getSource(20);int[][] myPackage = multiKnasackBest(source);for (int i = 0; i < myPackage.length; i++) {System.out.print("第" + i + "个箱子:");for (int i1 = 0; i1 < myPackage[i].length; i1++) {if (myPackage[i][i1] > 0) {System.out.print(myPackage[i][i1] + ", ");}}System.out.println();}}
}
脱机算法
  • 如果我们能够观察全部物品在给出答案,那么我们应该会做的更好。实时确实如此,我们通过彻底的搜索总能找到最优的装箱方法,因此我们对联机的情况下进行改进

  • 我们联机算法中,主要问题在于大项物品装箱困难,特别是当他们输入的后期出现的时候,总要新建立一个箱子。我们脱机算法中先将物品按照权重排序,这样大的在前面。次数我们应用首次适合算法,或者最佳适合算法得到解决,他们分别是首次适合递减算法最佳适合递减算法

  • 首次适合递减算法算法实现:

/*** 近似装箱问题 - 联机算法 - 脱机算法** @author liaojiamin* @Date:Created in 14:12 2021/1/15*/
public class KnapsackProblem {private static final int MAX_WEIGHT = 10;/*** 随机生成10 以内的物品数据*/public static int[] getSource(int num) {int[] source = new int[num];Random random = new Random();for (int i = 0; i < num; i++) {source[i] = random.nextInt(10);System.out.println(source[i]);}return source;}public static int[][] multiknasackDecreasing(int[] source){quickSort(source, 0, source.length - 1);return multiKnasackFirst(source);}/*** 快排从大到小* */public static void quickSort(int[] source, int left, int right){if(left > right){int temp = swap(source, left, right);quickSort(source, left, temp - 1);quickSort(source, temp + 1, right);}}public static int swap(int[] source, int left, int right){if (left < right){int position = source[left];while (left < right){while(left < right && position > source[right]){right --;}if(left < right){source[right] = source[left];left ++;}while (left < right && position < source[left]){left ++;}if(left < right){source[left] = source[right];right --;}}source[left] = position;}return left;}/*** 首次适合算法:* 义序草庙箱子,并把新的一项物品放入能容纳的箱子中* */public static int[][] multiKnasackFirst(int[] source ){int num = source.length;int[][] myPackage = new int[num][num];int[] position = new int[num];int[] weight = new int[num];int packagePosition = 0;for (int i = 0; i < source.length; i++) {boolean isInsert = false;for (int j = 0; j < weight.length; j++) {if(MAX_WEIGHT - weight[j] >= source[i]){isInsert = true;myPackage[j][position[j]] = source[i];weight[j] += source[i];position[j] += 1;break;}}if(!isInsert){packagePosition ++;myPackage[packagePosition][position[packagePosition]] = source[i];weight[packagePosition] += source[i];position[packagePosition] += 1;}}return myPackage;}public static void main(String[] args) {int[] source = getSource(20);int[][] myPackage = multiknasackDecreasing(source);for (int i = 0; i < myPackage.length; i++) {System.out.print("第" + i + "个箱子:");for (int i1 = 0; i1 < myPackage[i].length; i1++) {if (myPackage[i][i1] > 0) {System.out.print(myPackage[i][i1] + ", ");}}System.out.println();}}
}

上一篇:数据结构与算法–贪婪算法
下一篇:数据结构与算法–分治算法

数据结构与算法--贪婪算法2相关推荐

  1. 数据结构与算法--分治算法-最大子序列和问题

    分治算法 用于设计算法的一种常用技巧–分治算法(divide and conquer).分治算法由两部分组成: 分(divide):递归然后借机较小的问题(基础情况除外) 治(conquer):然后从 ...

  2. 数据结构与算法--图论-深度优先搜索及其应用

    深度优先搜索 深度优先搜索(depth-first search) 是对先序遍历(preorder traversal)的推广,我们从某个顶点v开始处理v,然后递归的遍历所有与v邻接顶点.如果这个过程 ...

  3. 「走过」微软、优步,老工程师告诉你哪些数据结构和算法最重要

    数据结构和基础算法作为计算机科学的必学课程,近几年却关注度越来越少.但程序员真的不再需要这两门基础知识了吗?一位在 Uber 等科技公司工作过的开发者分享了他的一手经验,告诉你实际工作中会用到哪些数据 ...

  4. 算法 | 数据结构与算法(代码版)

    ================================================= 博主github:https://github.com/MichaelBeechan 博主CSDN: ...

  5. GitHub 上值得前端学习的数据结构与算法项目

    Hello,大家好,我是你们的 前端章鱼猫. 简介 前端章鱼猫从 2016 年加入 GitHub,到现在的 2020 年,快整整 5 个年头了. 相信很多人都没有逛 GitHub 的习惯,因此总会有开 ...

  6. 数据结构与算法 Big O 备忘录与现实

    不论今天的计算机技术变化,新技术的出现,所有都是来自数据结构与算法基础.我们需要温故而知新. 算法.架构.策略.机器学习之间的关系.在过往和技术人员交流时,很多人对算法和架构之间的关系感到不可理解,算 ...

  7. 算法与数据结构_数据结构与算法专题--算法基本概念

    很多开发者都知道"程序=数据结构+算法"这个著名的公式,并不真正明白算法的定义或概念.究竟什么是算法呢?从字面意义上理解,算法即用于计算的方法,通过这种方法可以达到预期的计算结果. ...

  8. python算法和数据结构_Python中的数据结构和算法

    python算法和数据结构 To 至 Leonardo da Vinci 达芬奇(Leonardo da Vinci) 介绍 (Introduction) The purpose of this ar ...

  9. python棋盘最短路径_Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例...

    本文实例讲述了Python数据结构与算法之图的最短路径(Dijkstra算法).分享给大家供大家参考,具体如下: # coding:utf-8 # Dijkstra算法--通过边实现松弛 # 指定一个 ...

最新文章

  1. c语言中结构体的用法
  2. git 第三天 SSH免密码登录 2
  3. docker之Dockerfile实践
  4. 一个关于php使用pdo方式进行数据库连接和处理的类
  5. 与鬼古女夜晚后海边的“恐怖”聚会
  6. Spring5 jar包下载
  7. 为什么说去中心化很重要
  8. ios Photos框架
  9. 使用Thumbnailator处理gif图片时遇到java.lang.ArrayIndexOutOfBoundsException: 4096异常处理
  10. python excel案例导入jira_Python操作Jira库常用方法解析
  11. mysqlbinlog: unknown variable 'default-character-s
  12. 控件内部显示不正确原因---没有调用layoutSubview的父类方法
  13. Code jock使用笔记
  14. 6U-VPX 高速固态存储板卡—— 外挂2片DDR3,8GB/s带宽,存储容量16TB (KU085)
  15. MySQL数据库的恢复-mysql数据库的恢复
  16. Mac部署Prometheus + Grafana监控
  17. 深富策略:“石化双雄”爆发 市场不确定性增大
  18. 岁月温柔-14 妈妈的烦恼 突然手无力摔倒
  19. POST /product/:id 获取单个商品
  20. 微信公众号支付开发配置

热门文章

  1. Android之android.system.ErrnoException: open failed: ENOENT (No such file or directory)
  2. 一个基础的 HTML 文档有哪些标签?(3)
  3. php本地的调试安装,教你本地安装、运行、调试PHP程序
  4. Linux怎么查询全部容器时间,linuxea:如何单单修改docker容器的系统时间
  5. vue2 怎么用vite_vue3vite简介
  6. 为什么饮料瓶大都是圆的,牛奶盒却是方的?原因你想不到
  7. 用魔法打开科学,孩子惊叫连连,想不爱科学都难!
  8. 10分钟让你快速掌握Excel的16项重要技巧
  9. 读书笔记-互联网思维必读10本书之一《免费》
  10. 二叉排序树与文件操作的设计与实现_堆排序就这么简单