曾記否,忘了>_<!
概述:
大二暑假,在家無聊,給一個“火急火燎”的同學寫的東西。一個數學建模選拔賽的題目,利用托盤的尺寸和貨物的尺寸計算出貨物的最優擺放方法。給出的解法是一個博士的論文(剛好是我們學校學報上的文章)。看了一天的論文,半夜靈感爆發寫出來的,最後又調整了一版。
題目:
托盤裝載問題
隨着我國經濟的發展,物資流動日益頻繁,以散裝、人工搬運爲主的傳統運輸存儲方式已遠遠不能現代物流的需要,托盤已成爲衡量一個國物流效率水平的重要標誌之一。中國作爲世界製造業中心,托盤市場潛力巨大,但是根據中國物流與採購聯合會托盤專業委員會於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