曾记否,忘了>_<!
概述:
大二暑假,在家无聊,给一个“火急火燎”的同学写的东西。一个数学建模选拔赛的题目,利用托盘的尺寸和货物的尺寸计算出货物的最优摆放方法。给出的解法是一个博士的论文(刚好是我们学校学报上的文章)。看了一天的论文,半夜灵感爆发写出来的,最后又调整了一版。
题目:
托盘装载问题
随着我国经济的发展,物资流动日益频繁,以散装、人工搬运为主的传统运输存储方式已远远不能现代物流的需要,托盘已成为衡量一个国物流效率水平的重要标志之一。中国作为世界制造业中心,托盘市场潜力巨大,但是根据中国物流与采购联合会托盘专业委员会于2009年发布的《第二次全国托盘现状研究报告》,我国目前拥有的托盘总量仅为1.9亿至2.2亿,而美国现拥有托盘总量约为20亿、日本7亿、欧盟30亿。可以预计今后我国托盘的总量将会以惊人的速度增长,物流托盘应用前景广阔,根据德国人Janer/Graefentein的设计法则,托盘面积的利用率增加5%,其包装成本约降低10%,因此研究如何在一个托盘中正交且不重叠地放置数目最多同尺寸的长方体箱子,即装盘装载问题(Pallet loading problem,PLP),对降低物流运输成本,提高托盘的使用效率具有重要的现实意义。
请查阅我国使用的托盘规格标准(4种),解答如下问题:
1200mm×l000mm、l200mm×800mm、1140mm×l140mm及1219mm×l016mm等4个托盘规格。
1. 若某箱子的长为86cm、宽为34cm,将其放在长、宽分别为1200cm、1000cm的托盘上,怎样放置箱子(包括个数、图谱),才能使托盘面积的利用率最大?
2. 附表列出了某大型企业用于包装产品的各种箱子的规格尺寸,建立模型并求出分别将这些箱子放到长、宽分别为1200cm、1000cm的托盘上使其表面利用率达到最大的放置箱子个数及方式?
3. 探讨建立一般模型,以此求出将任意规格的箱子放到某一规格的托盘上使其利用率达到最大的装箱方式?
附表:某企业生产纸箱的规格尺寸(单位:cm)
序号 | 长 | 宽 | 序号 | 长 | 宽 |
1 | 310 | 222 | 31 | 185 | 94 |
2 | 319 | 275 | 32 | 113 | 57 |
3 | 326 | 190 | 33 | 188 | 94 |
4 | 322 | 193 | 34 | 214 | 106 |
5 | 352 | 197 | 35 | 190 | 93 |
6 | 251 | 190 | 36 | 384 | 186 |
7 | 277 | 237 | 37 | 393 | 189 |
8 | 551 | 362 | 38 | 220 | 105 |
9 | 309 | 231 | 39 | 183 | 86 |
10 | 319 | 276 | 40 | 148 | 69 |
11 | 548 | 361 | 41 | 148 | 69 |
12 | 330 | 195 | 42 | 293 | 134 |
13 | 327 | 295 | 43 | 223 | 101 |
14 | 320 | 314 | 44 | 223 | 100 |
15 | 308 | 224 | 45 | 313 | 140 |
16 | 284 | 264 | 46 | 197 | 87 |
17 | 364 | 251 | 47 | 289 | 127 |
18 | 341 | 251 | 48 | 162 | 70 |
19 | 305 | 222 | 49 | 155 | 67 |
20 | 357 | 250 | 50 | 275 | 118 |
21 | 273 | 261 | 51 | 124 | 53 |
22 | 279 | 170 | 52 | 237 | 100 |
23 | 319 | 207 | 53 | 371 | 155 |
24 | 269 | 181 | 54 | 178 | 74 |
25 | 534 | 417 | 55 | 335 | 137 |
26 | 343 | 273 | 56 | 213 | 87 |
27 | 311 | 253 | 57 | 186 | 75 |
28 | 355 | 253 | 58 | 375 | 150 |
29 | 397 | 269 | 59 | 289 | 115 |
30 | 442 | 290 | 60 | 288 | 113 |
算法引用的论文:
C语言简单的算法实现:
#include<stdio.h>
//#include<stdlib.h>
#include<math.h>
void main()
{
float x,y,x1,y1,x2,y2;//这些参量用于调试,后期可能无用
int i,j,k=0;
int NLl=0,NLw=0,NWl=0,NWw=0;
float L,W,L1,W1,L2,W2;
float l,w;
float min1,min2,t,a1,b1,a2,b2;
int DH,DV;
float s1;
int sum,a3,b3,sum1,a4,b4;
int Dd;//干涉时减少箱子的个数
printf("请输入托盘的长宽\n");
scanf("%f %f",&L,&W);
printf("请输入货物的长宽\n");
scanf("%f %f",&l,&w);
loop1: if(L>l&&W>w)//判断是否能装上平台,对应算法一第1步
{
k++;
a1=L/l;
b1=L/w;
min1=L;
for(i=0;i<=a1;i++)//求NLl类,对应算法一第2步
{
for(j=0;j<=b1;j++)
{
t=L-i*l-j*w;
if(min1>t&&t>=0)
{
min1=t,NLl=i,NLw=j;
}
}
}
printf("第%d次环绕结果,NLl=%d,NLw=%d,min1=%f\n",k,NLl,NLw,min1);
a2=W/l;
b2=W/w;
min2=W;
for(i=0;i<=a2;i++)//求NWl类,对应算法一第3步
{
for(j=0;j<=b2;j++)
{
t=W-i*l-j*w;
if(min2>t&&t>=0)
{
min2=t,NWl=i,NWw=j;
}
}
}
printf("第%d次环绕结果,NWl=%d,NWw=%d,min2=%f\n",k,NWl,NWw,min2);
if(NLl*NLw*NWl*NWw!=0)//&&(L-NLl*l*2)*(W-NWl*l*2)>0
printf("第%d次环绕堆放了%d个箱子\n",k,2*(NLl*NWw+NLw*NWl));
L1=abs(L-NLl*l*2);
W1=abs(W-NWl*l*2);
printf("L1=%f,W1=%f\n",L1,W1);
if(NLl*NLw*NWl*NWw==0)//判断以便分类算法,对应算法一第4步
{
if(NLl==0&&NWw==0)
{
a3=(int)(L/w);
b3=(int)(W/l);
sum=a3*b3;
printf("该区域采用图8a的排列方法,能容纳%d个\n",sum);
}
//调用算法三,这里会很长,还没来得及看
if(NLw==0&&NWl==0)
{
a3=(int)(L/l);
b3=(int)(W/w);
sum=a3*b3;
printf("该区域采用图8b的排列方法,能容纳%d个\n",sum);
}
if(NLw==0&&NWw==0)
{
a3=(int)(L/w);
b3=(int)(W/l);
sum=a3*b3;
a4=(int)(L/l);
b4=(int)(W/w);
sum1=a3*b3;
if(sum>sum1)
{
printf("该区域采用图8a的排列方法,能容纳%d个\n",sum);
}
else
{
printf("该区域采用图8b的排列方法,能容纳%d个\n",sum1);
}
}
if(NLl==0&&NWl==0)
{
a3=(int)(L/w);
b3=(int)(W/l);
sum=a3*b3;
a4=(int)(L/l);
b4=(int)(W/w);
sum1=a4*b4;
printf("sum=%d,sum1=%d\n",sum,sum1);
if(sum>sum1)
{
printf("该区域采用图8c的排列方法,能容纳%d个\n",sum);
L1=L;
W1=W-b3*l;
if(L1>W1)
{
L=L1;
W=W1;
}
else
{
L=W1;
W=L1;
}
goto loop1;
}
else
{
printf("该区域采用图8d的排列方法,能容纳%d个\n",sum1);
L1=L-a4*l;
W1=W;
if(L1>W1)
{
L=L1;
W=W1;
}
else
{
L=W1;
W=L1;
}
printf("L1=%f,W1=%f\n",L1,W1);
printf("a4=%d\n",a4);
goto loop1;
}
}
if(NLl==0&&(NLw*NWl*NWw))
{
a3=(int)(L/l);
sum=NLw*NWl+NWw*a3;
printf("该区域采用图8e的排列方法,能容纳%d个\n",sum);
L1= L-(int)(L/l)*l;
W1=W-NWl*l;
if(L1>W1)
{
L=L1;
W=W1;
}
else
{
L=W1;
W=L1;
}
goto loop1;
}
if(NLw==0&&(NLl*NWl*NWw))
{
//a3=(int)(L/l);
b3=(int)(L/w);
sum=NWw*NLl+b3*NWl;
printf("该区域采用图8f的排列方法,能容纳%d个\n",sum);
}
if(NWl==0&&(NLl*NLw*NWw))
{
b3=(int)(W/l);
sum=NWw*NLl+NLw*b3;
L1=W-NLl*l;
W1=W-(int)(W/l)*l;
printf("该区域采用图8g的排列方法,能容纳%d个\n",sum);
if(L1>W1)
{
L=L1;
W=W1;
}
else
{
L=W1;
W=L1;
}
//L=L1;
//W=W1;
goto loop1;
}
if(NWw==0&&(NLl*NLw*NWl))
{
b3=(int)(W/w);
sum=NLw*NWl+NLl*b3;
printf("该区域采用图8h的排列方法,能容纳%d个\n",sum);
}
}
else//对应算法一第5步
{
s1=(L-NLl*l*2)*(W-NWl*l*2);
// x=L-NLl*l*2;
// y=W-NWl*l*2;
// printf("x=%f,y=%f\n",x,y);
// printf("s1=%f\n",s1);
if(s1>0)
{
L=L1,W=W1;
//x1=NLl*l;
//x2=NLw*w;
//y1=NWl*l;
//y2=NWw*w;
//printf("x1=%f,x2=%f,y1=%f,y2=%f\n",x1,x2,y1,y2);
goto loop1;//使用goto语句跳转到算法一的第1步
}
else//调用算法二对应算法一的第6步,产生干涉用算法二调整
{
//x1=NLl*l;
//x2=NLw*w;
//y1=NWl*l;
//y2=NWw*w;
//printf("x1=%f,x2=%f,y1=%f,y2=%f\n",x1,x2,y1,y2);
if(NLl*l<NLw*w&&NWl*l>NWw*w)//A区发生干涉
{
DH =(int)(W1/l-0.1)+1;
DV= (int)(L1/w-0.1)+1;
Dd=DH*DV;
//printf("DH=%d,DV=%d\n",DH,DV);
printf("因为A区发生干涉,因减掉%d行,%d列,共%d个\n",DH,DV,Dd);
L2=DV*w;
W2=DH*l-W1;
printf("L2=%f,W2=%f\n",L2,W2);
if(L2>W2)
{
L=L2;
W=W2;
}
else
{
L=W2;
W=L2;
}
goto loop1;
}
if(NLl*l>NLw*w&&NWl*l<NWw*w)//B区发生干涉
{
DH =(int)(W1/w-0.1)+1;
DV= (int)(L1/l-0.1)+1;
Dd=DH*DV;
//printf("DH=%d,/V=%d\n",DH,DV);
printf("因为B区发生干涉,因减掉%d行,%d列,共%d个\n",DH,DV,Dd);
L2=DV*l-L1;
W2=DH*w;
printf("L2=%f,W2=%f\n",L2,W2);
if(L2>W2)
{
L=L2;
W=W2;
}
else
{
L=W2;
W=L2;
}
goto loop1;
}
//goto loop1;
}
}
}
}//haha制作者代码00110111101000001111011011111001001011