第06讲 装箱问题
- 格式:ppt
- 大小:387.00 KB
- 文档页数:27
贪⼼算法之装箱问题问题描述装箱问题可简述如下:设有编号为 0、1、…、n - 1 的 n 种物品,体积分别为v0、v1、…、vn-1。
将这 n 种物品装到容量都为 V 的若⼲箱⼦⾥。
约定这 n 种物品的体积均不超过 V,即对于 0≤ i<n,有 0<vi ≤ v。
不同的装箱⽅案所需要的箱⼦数⽬可能不同。
装箱问题要求使装尽这 n 种物品的箱⼦数要少。
贪⼼求解使⽤⼀种贪⼼策略:每次都想将当前体积最⼤的物品装⼊箱中,在这块类似于这个问题 ->>>其实在⽣活中这也是很常见的⼀种做法,在没有充⾜时间去考虑如何最优解决这类问题时直觉(第六感狗头保命)告诉我们可以这么去试试。
更直接的⼀个例⼦,⼒扣上有这么⼀道题:在柠檬⽔摊上,每⼀杯柠檬⽔的售价为 5 美元。
顾客排队购买你的产品,(按账单 bills ⽀付的顺序)⼀次购买⼀杯。
每位顾客只买⼀杯柠檬⽔,然后向你付 5 美元、10 美元或20美元。
你必须给每个顾客正确找零,也就是说净交易是每位顾客向你⽀付 5 美元。
注意,⼀开始你⼿头没有任何零钱。
注:上⾯⿊体部分内容引⾃很明显,当客户给我们$20进⾏找零时,⾃然⽽然地就给ta找了⼀张$10加上⼀张$5,为什么这么做?⾯对$20,我们有两种⽅案可以使⽤:找三张$5给顾客找⼀张$10 以及⼀张 $5 给顾客选择第⼆种⽅案的原因对于做⽣意的⽼板应该不陌⽣,营业过程中我们需要备上⼀部分零钱在交易时⽅便找零,不⾄于出现⽆法找零的尴尬局⾯,这是商⼈们所想的,在上题中也同样适⽤。
但贪⼼算法的弊端也很明显:不考虑之前解带来的影响,仅仅为了达到当前最优解,这样”⼀根筋“的策略也不能在任何情况下得到最优解。
如只有⾯值分别为 1、5 和 11 单位的硬币,⽽希望找回总额为 15 单位的硬币。
按贪婪算法,应找 1 个 11 单位⾯值的硬币和 4 个 1 单位⾯值的硬币,共找回 5 个硬币。
但最优的解应是 3 个 5 单位⾯值的硬币。
装箱问题{2001p4--穷举法}问题描述有一个箱子容量为V(正整数,0<=V<=20000),同时有N个物品(0<n<=30),每个物品的体积值为正整数。
要求从n个物品中,选取若干个装入箱内,使箱子的剩余空间最小。
输入:1行整数,第一个数表示箱子的容量,第二个数表示有n个物品,后面n个数分别表示这n个物品各自的体积。
输出:1个整数,表示箱子的剩余空间。
输入输出样例:输入:24 6 8 3 12 7 9 7输出:简单穷举varv,n,I,j:integer;w: array[1 .. 30] of integer; {存储N件物品的体积}a: array[0 .. 30] of integer; {存储N件物品的选取状态,1表示选取,0表示不选取} min,:Integer; {统计最小剩余量}s:integer; {累加器,统计物品体积和}beginread(v);min:=v; {初始时设定空间最小剩余量为箱子总容量}read(n);for i:=1 to n do read(w[i]);for i:=0 to n do a[i]:=0;while a[0]=0 do { a[0]作为循环控制开关}beginj:=n;while a[j]=1 do j:=j-1; {逢一进位}a[j]:=1; {设定新的状态}for i:=j+1 to n do a[i]:=0;s:=0;for i:=1 to n do s:=s+a[i]*w[i]; {计算物品的体积和}if (v-s>=0) and (v-s<min) then min:=v-s; { min存储目前的最小剩余量}end;writeln(min);end.穷举改进varv,n:integer;w: array[1 .. 30] of integer;a: array[0 .. 30] of integer;i,j,min,s,temp:Integer;beginread(v);min:=v;read(n);for i:=1 to n do read(w[i]);for i:=1 to n-1 do {排序}for j:=i+1 to n doif w[i]>w[j] thenbegintemp:=w[i]; w[i]:=w[j]; w[j]:=temp;end;for i:=0 to n do a[i]:=0;while a[0]=0 dobeginj:=n;while a[j]=1 do j:=j-1;a[j]:=1;for i:=j+1 to n do a[i]:=0;s:=0;for i:=1 to n do s:=s+a[i]*w[i];if v<s then for i:=j+1 to n do a[i]:=1 {体积总和超过容量,不再继续穷举} else if v-s<min then min:=v-s; {更正min }end;writeln(min);end.。
承诺书我们仔细阅读了中国大学生数学建模竞赛的竞赛规则.我们完全明白,在竞赛开始后参赛队员不能以任何方式(包括电话、电子邮件、网上咨询等)与队外的任何人(包括指导教师)研究、讨论与赛题有关的问题。
我们知道,抄袭别人的成果是违反竞赛规则的, 如果引用别人的成果或其他公开的资料(包括网上查到的资料),必须按照规定的参考文献的表述方式在正文引用处和参考文献中明确列出。
我们郑重承诺,严格遵守竞赛规则,以保证竞赛的公正、公平性。
如有违反竞赛规则的行为,我们将受到严肃处理。
我们参赛选择的题号是(从A/B/C/D中选择一项填写): A我们的参赛报名号为(如果赛区设置报名号的话):所属学校(请填写完整的全名):参赛队员(打印并签名) :1.2.3.指导教师或指导教师组负责人(打印并签名):日期: 2011 年 07 月 16 日赛区评阅编号(由赛区组委会评阅前进行编号):编号专用页赛区评阅编号(由赛区组委会评阅前进行编号):全国统一编号(由赛区组委会送交全国前编号):全国评阅编号(由全国组委会评阅前进行编号):摘要题目要求及有关数据我们可以把平板车装包装箱问题看成线性规划的问题进行处理,首先我们把求浪费空间最小转化为求装包装箱空间最大的问题,同时我们取每种包装箱的数量为变量,然后我们根据每一种包装箱的厚度列出每一辆车的装货时占用的空间,我们先把两辆车看成一个整体,求出两辆车占用的空间之和,然后再把这个整体分成两部分,也就是求每一辆车上所装包装箱的种类和数量。
这样我们就可以以占用两辆车的空间之和作为目标函数MAX S。
根据题意装在每一辆车上的包装箱总厚度不能超过平板车的长度;装在每一辆车上的总重量不能超过每一辆平板车的最大载重量;还有对第5、6、7类包装箱占用的空间不能超过题目中的要求;同时,装在两辆车上的同类包装箱的总件数不能超过题目给的件数,并且变量要取正整数。
在这些约束条件之下对目标函数进行求解,我们使用LINGO软件进行编程求解,最后得到装包装箱的总的最大空间为2039.9cm,即浪费的最小空间为0.1cm。
三年级乘除混合应用题装箱问题摘要:1.问题背景和意义2.乘除混合应用题的基本类型3.装箱问题的解决方法4.实际应用与练习5.总结与建议正文:随着年龄的增长,孩子们的数学能力也在不断提高。
乘除混合应用题是三年级数学学习中的一项重要内容,不仅能够检验学生对乘法和除法运算的掌握程度,还能培养他们的逻辑思维能力。
本文将以乘除混合应用题的装箱问题为例,详细介绍这类问题的解决方法,以帮助孩子们更好地应对这类题目。
一、问题背景和意义在现实生活中,装箱问题是一种非常常见的情况。
例如,在物流运输、商品销售等领域,我们需要将不同尺寸的物品装入容器中,以求最大限度地利用空间。
乘除混合应用题的装箱问题就是在此基础上提出的,它要求学生在解答过程中运用乘法和除法运算。
二、乘除混合应用题的基本类型乘除混合应用题的装箱问题主要包括以下几种类型:1.给定容器体积和物品体积,求最多可以装多少个物品。
2.给定物品体积和容器数量,求每个容器最多可以装多少个物品。
3.给定容器体积和物品数量,求最少需要多少个容器。
4.给定物品体积、容器数量和每个容器的装载量,求最多可以装多少个物品。
三、装箱问题的解决方法1.理解题意,确定解题目标。
首先要明确题目要求求解的是最多可以装多少个物品、每个容器最多可以装多少个物品、最少需要多少个容器等问题。
2.分析数据关系。
根据题目给出的数据,找出物品体积、容器体积和装载量之间的关系。
3.运用乘除法运算。
根据分析得出的关系,将数据代入相应的公式进行计算。
4.结合实际情境,进行合理推断。
在计算过程中,要结合实际情境进行合理推断,例如:当物品体积大于容器体积时,无法装入;当物品体积小于容器体积时,可以装入一个容器;当物品体积等于容器体积时,最多可以装入一个容器。
四、实际应用与练习为了更好地掌握乘除混合应用题的装箱问题,我们可以通过以下实际应用和练习进行巩固:1.妈妈买了5斤苹果,每斤10元,一共需要支付多少钱?2.一个集装箱长10米,宽6米,高4米,另一个集装箱长8米,宽4米,高2米。
装箱问题算法实现讲解有一个箱子容量为V(正整数,0≤V≤20000),同时有n个物品(0≤n≤30),每个物品有一个体积(正整数)。
要求从n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
[样例]输入:24 一个整数,表示箱子容量6 一个整数,表示有n个物品8 接下来n行,分别表示这n个物品的各自体积。
312797输出:0 一个整数,表示箱子剩余空间算法分析:本题是经典问题:0-1背包的特殊例子(加强了已知条件)。
用整形数组volume存储各件物品的体积,用布尔型函数h(i,k)表示前i个物品通过组合能否恰好装满容量k的空间,则考虑第i件物品,如果没有被选中,则问题转化为h(i-1,k);如果第i件物品被选中了,则问题转化为h(i-1,k-volume[i]),因此有如下的表达式:h(i,k)=h(i-1,k-volume[i]) || h(i-1,k);k从V开始递减,判断h(n,k)是否为真,第一个符号要求的k即为剩余空间最小时消耗的体积。
如果此时直接编写程序,就要定义一个二维数组,空间复杂度时n*v,注意到了n,v的取值范围很大,所以用二维数组存储就会有问题。
我们注意到,h(i,k)的取值仅与h(i-1,0)~h(i-1,k)有关,且如果h(i-1,k)=true,必然有h(i,k)=true,h(i,k)的值存在继承性,而程序结束时,我们也只关心h(n,k),因此,我们可以用一维数组h(k)来存储中间信息。
为了避免重复计算,可以让k从大到小变化,为了避免出现负数,k的变化范围为v~volume[i].示例程序:#include<iostream>#include<cstring>using namespace std;int v,n;int volume[31];//存储n件物品的体积int h[20001];//h[i]=1,表示n件物品通过某种组合,所构成的体积和正和等于i;//h[i]=0,表示n件物品无论如何组合,体积和都无法等于iint main(){freopen(\"in.txt\",\"r\",stdin);freopen(\"out.txt\",\"w\",stdout);int v,n,i,j,k;while(cin>>v>>n){for(i=1;i<=n;i++)cin>>volume[i];memset(h,0,sizeof(h));h[0]=1;for(i=1;i<=n;i++)for(k=v;k>=volume[i];k--)h[k]=h[k]||h[k-volume[i]];[Page]j=v;while(j>0&&h[j]==0)j--;cout<<v-j<<endl;}return 0;。
背包与装箱问题
一. 背包问题
某人旅游,要带n 件物品,重量分别为i a (i=1….n )但受到航空
行李重量及体力的限制,能带行李总重量为b ,n 件物品的重量和超过了b ,该怎样抉择。
假设有8件物品,重量分别为:1,3,4,3,3,1,5,10(kg ) 价值分别为:2,9,3,8,10,6,4,10(元)
重量总限制:15kg
如何选择物品使总价值最大。
模型为:
8
i=18i=1max z=x (x 0-1s.t x 15 (i=1,2...8)
i i i i i i c c a ≤∑∑为变量;为物品价值)
二. 装箱问题
设有许多长为C 的一维箱子,及长为 () 1,2i i W W C i n <= 的n 件物品,要把这些物品全部装如箱子中,怎样装法使得所用箱子竟可能的少?
已知30个物品,其中6个长0.51m ,6个长0.27m ,6个长0.26m 余下12个长0.23m ,箱子长度1m 。
问最少需要多少箱子可以把30件物品全部装下。
先准备30个箱子,每个箱子就装一件物品,用0-1变量j y 表示第
j 个箱子是否使用,用0-1变量ij x 表示第i 件物品是否放入第j 个箱子。
建模如下:
30j j=130
i=1
30
1min z=y .
, 130; ,
130;i ij
j ij j s t w x Cy j x i =≤
==∑∑∑。
某厂生产一种弹子锁具,每个锁具的钥匙有5个槽,每个槽的高度从{1,2,3,4,5,6}6个数(单位略)中任取一个,由于工艺及其他原因,制造锁具时对5个槽的高度有两个限定:至少有3个不同的数;相邻两槽的高度之差不能为5。
满足以上条件制造出来的所有互不相同的锁具称为一批。
从顾客的利益出发,自然希望在每批锁具中“一把钥匙开一把锁”。
但是在当前工艺条件下,对于同一批中两个锁是否能够互开,有一下实验结果:若二者相对应的5个槽的高度中有4个相同,另一个槽的高度差为1,则可能互开;在其他情形下,不可能互开。
原来,销售部门在一批锁具中随意地取60个装成一箱出售。
团体顾客往往购买几箱到几十箱,他们抱怨购买的锁具会出现互开的情形。
现聘你为顾问,回答并解决以下问题:①每一批锁具有多少个?装多少箱?②为销售部门提出一种方案,包括如何装箱(仍是60个锁具一箱),如何给箱子以标志,出售时如何利用这些标志,使团体顾客不再或减少抱怨。
③采取你提出的方案,团体顾客的购买量不超过多少箱,就可以保证一定不会出现互开的情形。
④按照原来的装箱方法,如何定量地衡量团体顾客抱怨互开的程度(试对购买一、二箱着给出具体结果)。
解:一、每批锁的把数第一问完全是一个数学问题,首先可以求出有5个槽、每个槽有6个高度的所有可能的个数为n1=65=7776,为了满足题目中提出的至少有三个不同的高度,且相邻高度差不应为5的要求,我们应该减去不满足要求的锁具。
在具体求每批锁的个数以及可以装多少箱时,既可以用排列组合法也可以编程用计算机求解。
这里我们用Matlab编程求解。
我们对5个钥匙槽的高度进行五重循环,并将判断条件设置为5个槽的高度中至少有3个不同的数且相邻两槽的高度之差不能为5,进行判断。
将满足判断条件的累加起来,最后输出即可得到一批锁具总数的大小。
可以装的箱数用锁具总数除于60即可得到。
程序如下:count=0;for h1=1:6a(1)= h1;for h2=1:6a(2)= h2;for h3=1:6a(3)= h3;for h4=1:6a(4)= h4;for h5=1:6a(5)= h5;s=0;flag=1;b=sort(a); c=diff(a);d=diff(b);for i=1:4if d(i)~=0s=s+1;endif abs(c(i))==5flag=0;endendif s>=2&flagcount=count+1;endendendendendendcountnbox=count/60程序运行结果为:count =5880nbox =98计算结果说明,每一批锁具有5880个,可以装98箱。