數學建模-托盤最優化擺放解法(大學時期留下的算法)

曾記否,忘了>_<!

概述:

大二暑假,在家無聊,給一個“火急火燎”的同學寫的東西。一個數學建模選拔賽的題目,利用托盤的尺寸和貨物的尺寸計算出貨物的最優擺放方法。給出的解法是一個博士的論文(剛好是我們學校學報上的文章)。看了一天的論文,半夜靈感爆發寫出來的,最後又調整了一版。

題目:

托盤裝載問題

隨着我國經濟的發展,物資流動日益頻繁,以散裝、人工搬運爲主的傳統運輸存儲方式已遠遠不能現代物流的需要,托盤已成爲衡量一個國物流效率水平的重要標誌之一。中國作爲世界製造業中心,托盤市場潛力巨大,但是根據中國物流與採購聯合會托盤專業委員會於2009年發佈的《第二次全國托盤現狀研究報告》,我國目前擁有的托盤總量僅爲1.9億至2.2億,而美國現擁有托盤總量約爲20億、日本7億、歐盟30億。可以預計今後我國托盤的總量將會以驚人的速度增長,物流托盤應用前景廣闊,根據德國人Janer/Graefentein的設計法則,托盤面積的利用率增加5%,其包裝成本約降低10%,因此研究如何在一個托盤中正交且不重疊地放置數目最多同尺寸的長方體箱子,即裝盤裝載問題(Pallet loading problem,PLP),對降低物流運輸成本,提高托盤的使用效率具有重要的現實意義。

請查閱我國使用的托盤規格標準(4種),解答如下問題:

1200mm×l000mml200mm×800mm1140mm×l140mm1219mm×l016mm4個托盤規格。

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

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章