数据结构与算法--贪婪算法2

近似装箱问题

  • 解决装箱问题(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();}}
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

哪种开源许可证最适合商业化?

选择最佳开源许可证是为新项目所做的最重要的决定之一。大多数开发者会选用 MIT、BSD 或 Apache 等流行的宽松许可证&#xff08;permissive license&#xff09;。对于商业项目而言&#xff0c;这种选择不错&#xff0c;因为这能减少用户对项目的抵触情绪。当应用于开源项目时…

C++泛型编程实现哈希表(开散列法)

代码如下: #include <iostream> #include <vector> using namespace std;template<typename K> struct HashNode {typedef HashNode<K> Node;K _val;Node * _next;HashNode(const K & val):_val(val),_next(nullptr){} };template<typename K&…

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

分治算法 用于设计算法的一种常用技巧–分治算法&#xff08;divide and conquer&#xff09;。分治算法由两部分组成&#xff1a; 分(divide)&#xff1a;递归然后借机较小的问题&#xff08;基础情况除外&#xff09;治(conquer)&#xff1a;然后从子问题的解构建原问题的解…

请把我不会,换成我可以学

点击蓝字关注&#xff0c;回复“职场进阶”获取职场进阶精品资料一份有位读者跟我说起自己的烦恼&#xff1a;“我到公司已经接近四年了&#xff0c;领导经常让我做一些岗位职责以外的事情。这些东西我都不会&#xff0c;还非让我做。并且一直没有职位上的改变&#xff0c;我怎…

[C++STL]C++实现unordermap容器和unorderset容器

代码如下: #include <iostream> #include <vector> using namespace std;template<typename K,typename V,typename KeyOfValue> class HashTable;//声明template<typename V> struct HashNode {typedef HashNode<V> Node;V _val;Node * _next;…

数据结构与算法--链表实现以及应用

数据结构与算法–链表实现以及应用 链表是面试时候使用最频繁的一种数据结构。链表的结构简单&#xff0c;他由指针将若干个节点链接成链状结构。链表的创建&#xff0c;插入&#xff0c;删除&#xff0c;查询操作都只有几行代码可以完成&#xff0c;代码量比较少&#xff0c;…

还不会docker+k8s?2020年,就要面对现实了...

docker的前世今生2010年&#xff0c;几个年轻人&#xff0c;在美国旧金山成立了一家名叫“dotCloud”的公司。这家公司主要提供基于PaaS的云计算技术服务。具体来说&#xff0c;是和LXC有关的容器技术。后来&#xff0c;dotCloud公司将自己的容器技术进行了简化和标准化&#x…

数据结构与算法--重建二叉树

二叉树 树在实际编程中经常遇到地一种数据结构。上一篇中我们解释了二叉树及其原理&#xff0c;从中可以知道&#xff0c;树地操作会涉及到很多指针地操作&#xff0c;我们一般遇到地树相关地问题差不多都是二叉树。二叉树最重要地莫过于遍历&#xff0c;即按照某一顺序访问树…

3分钟掌握Quartz.net分布式定时任务的姿势

长话短说&#xff0c;今天聊一聊分布式定时任务&#xff0c;我的流水账笔记&#xff1a;ASP.NET CoreQuartz.Net实现web定时任务AspNetCore结合Redis实践消息队列细心朋友稍一分析&#xff0c;就知道还有问题&#xff1a;水平扩展后的WebApp的Quartz.net定时任务会多次触发&…

C++ 实现布隆过滤器(BloomFilter)

代码如下: #include <iostream> #include <vector> using namespace std;class BitMap { public:BitMap(size_t range) :_bit(range / 32 1) {}void set(const size_t num){int idx num / 32;//idx 数组下标int bitIdx num % 32;_bit[idx] | 1 << bitIdx…

数据结构与算法--利用栈实现队列

利用栈实现队列 上一节中说明了栈的特点 后进先出&#xff0c;我们用数组的方式实现了栈的基本操作api&#xff0c;因此我们对栈的操作是不考虑排序的&#xff0c;每个api的操作基本都是O(1)的世界&#xff0c;因为不考虑顺序&#xff0c;所以找最大&#xff0c;最小值&#x…

ASP.NET Core 配置源:实时生效

在之前的文章 ASP.NET Core 自定义配置源 和 ASP.NET Core etcd 配置源 中主要是介绍如何实现自定义的配置源&#xff0c;但不论内置的和自定义的配置源&#xff0c;都会面临如何使配置修改后实时生效的问题&#xff08;修改配置后在不重启服务的情况下能马上生效&#xff09;。…

分布式事务理论模型

分布式事务 事务的概念&#xff0c;我们第一想到的应该是数据库的事务。所谓数据库事务就是只作为单个逻辑工作单元执行多个数据库操作的时候&#xff0c;数据库需要保证要么都成功&#xff0c;要么都失败&#xff0c;它必须满足ACID特性&#xff0c;即&#xff1a; 原子性&…

[MySQL基础]数据库的相关概念

DB: 数据库(database):存储数据的“仓库”&#xff0c;它保存了一系列有组织的数据。 DBMS: 数据库管理系统(Database Management System):数据库是通过DBMS创建和操作的容器。 SQL: 结构化查询语言(Structure Query Language):专门用来与数据库通信的语言。 SQL的优点: 1.几…

Linq下有一个非常实用的SelectMany方法,很多人却不会用

在平时开发中经常会看到有些朋友或者同事在写代码时会充斥着各种for&#xff0c;foreach&#xff0c;这种程式代码太多的话阅读性特别差&#xff0c;而且还显得特别累赘&#xff0c;其实在FCL中有很多帮助我们提高阅读感的方法&#xff0c;而现实中很多人不会用或者说不知道&am…

.NET Core前后端分离快速开发框架(Core.3.1+AntdVue)

引言时间真快&#xff0c;转眼今年又要过去了。回想今年&#xff0c;依次开源发布了Colder.Fx.Net.AdminLTE(254Star)、Colder.Fx.Core.AdminLTE(335Star)、DotNettySocket(82Star)、IdHelper(47Star)&#xff0c;这些框架及组件都是本着以实际出发&#xff0c;实事求是的态度&…

数据结构与算法--查找与排序另类用法-旋转数组中的最小数字

查找与排序 查找 查找与排序都在程序设计中常被用到的算法。查找相对而言简单&#xff0c;一般都是顺序查找&#xff0c;二分查找&#xff0c;哈希表查找&#xff0c;和二叉排序树查找。其中二分查找是我必须熟悉的一种。哈希表和二叉排序树主要点在于他的数据结构而不是算法…

[MySQL基础]MySQL常见命令介绍

show databases; use 库名; show tables; show tables from 库名 select database(); create table 名字( id int, name varchar(20)); desc 表名; select * from 表名; insert into 表名 (a,b,…,f) values(1,2,3,…,7); update 库名 set name‘lilei’ where id1; delete f…

如何选择好公司

点击蓝字关注&#xff0c;回复“职场进阶”获取职场进阶精品资料一份前几天写了一篇文章&#xff1a;怎么判断自己在不在一家好公司。附带了一个投票调查&#xff0c;结果如下图&#xff1a;调研结果有点点扎心&#xff0c;有点点出乎我的意料。61%的小伙伴&#xff0c;都认为自…