# 贪心算法之木材装集装箱问题

贪心算法应用

——木材的装箱问题

——采用贪心算法思想，将箱子抽象为L*W*H的长方体，将木材抽象为底面半径为ri、长为L的圆柱体。

1、首先对圆柱体按半径大小从大到小进行排序

2、取出圆柱体中底面半径最大的一个，从左下角坐标开始检查矩形空闲位置并判断当前圆柱体是否可以放入（判断圆柱体底面圆的圆心距是否合适，以及底面面积是否超过了空闲矩形的边框）。

3、接下来再将剩余的圆柱体取出，重复步骤2直至矩形空间中不再能够容纳下剩余圆柱体中底

#include <iostream>
#include <stdio.h>
#include <graphics.h>
#include <conio.h>
#include <math.h>
//#include <stdlib.h>
using namespace std;

#define MAXNUM 100
#define pi 3.141592653589

int columnum,count;
float H,W;

struct Circle_wood //圆柱形木头的数据结构
{
double x,y,r;
int sel;      //判断是否和别人相交
}cr[MAXNUM];

double dis(Circle_wood a,double x,double y) //两个圆圆心距
{
return sqrt((a.x-x)*(a.x-x)+(a.y-y)*(a.y-y));
}

int sort(Circle_wood *wood,int n)//按圆柱半径由大到小排序
{
Circle_wood a;
int j;
for(int i=0;i<columnum;i++)
{
a=wood[i];
j=i-1;
while(j>=0 && wood[j].r<a.r)
{
wood[j+1]=wood[j];
j=j-1;
}
wood[j+1]=a;
}

return 0;
}

int put(int now,double tx,double ty)//判断在位置(tx,ty)是否可以放下
{
if(tx<cr[now].r || tx+cr[now].r>W || ty<cr[now].r || ty+cr[now].r>H)
return 0; //不能放下，越界
for(int i=0;i<now;i++)
if(cr[i].sel)//判断是否和别人相交
if(dis(cr[i],tx,ty)<(cr[i].r+cr[now].r-0.01)) //相交
return 0;
return 1;
}

void check(int now)//为第now个木头找位置
{
double t,dx,dy;
for(int i=0;i<now;i++)
if(cr[i].sel)//对每个已插入的木头
{
t=cr[i].r+cr[now].r;
for(int j=0;j<=360; j++)//对每个角度进行检查
{
dx=cr[i].x+t*cos(-pi/2.0 + j*pi/180.0);
dy=cr[i].y+t*sin(-pi/2.0 + j*pi/180.0);
if(put(now,dx,dy)==1)//找到合适位置了
{
count++;
cr[now].x=dx;
cr[now].y=dy;
cr[now].sel=1;
return ;
}
}
}
}

void Gdy()//确定坐标并实现木材的定位
{
count=0;int i;
for(i=0;i<columnum;i++) //初始化
cr[i].sel=0;
for(i=0;i<columnum;i++)
{
if(count==0 && cr[i].r <= H/2 &&cr[i].r <=W/2)//第一个能放进的
{
cr[i].x=cr[i].r;
cr[i].y=cr[i].r;
cr[i].sel=1;
count++;
}
else
check(i); //检查其他木头
}

}

void draw()//画图
{
int t=0;
int k,j;
char *S[MAXNUM]={"0 ","1 ","2 ","3 ","4 ","5 ","6 ","7 ","8 ","9 ","10","11","12","13","14","15","16","17","18","19","20",
"21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45"};
/*
int *S[20];
for(k=0,j=0;k<columnum;k++)
{
if(cr[k].sel==1)
{
*S[j]=(int)cr[k].r;
j++;
}
}
*/
HBRUSH hbrush_old;
HDC    hdc     = GetWindowDC( GetDesktopWindow() );
HPEN   hpen1   = CreatePen( PS_SOLID, 1, RGB(255,200,200) );// 创建浅色1像素宽度的实线画笔
HPEN   hpen2   = CreatePen( PS_DASH, 5, RGB(0,255,0) ); // 创建绿色5像素宽度的破折画笔
HBRUSH hbrush1 = CreateSolidBrush( RGB(60,60,60) ); // 创建一个实体蓝色画刷
HBRUSH hbrush2 = CreateSolidBrush( RGB(255,255,255) ); //紫色
//HBRUSH hbrush3 = CreateSolidBrush( RGB(0,255,64) );//绿色
//HBRUSH hbrush4 = CreateSolidBrush( RGB(128,255,0) );
//HBRUSH hbrush5 = CreateSolidBrush( RGB(255,0,128) );//紫色

HPEN   hpen_old= (HPEN)SelectObject( hdc, hpen1 );
hbrush_old     = (HBRUSH)SelectObject( hdc, hbrush1);
Rectangle(hdc,200,400,200+(int)(W*20),400-(int)(H*20));
for(int i=0;i<columnum;i++)
{
if(i%4==0)
hbrush_old = (HBRUSH)SelectObject( hdc, hbrush2);
else if(i%4==1)
hbrush_old = (HBRUSH)SelectObject( hdc, hbrush2);
else if(i%4==2)
hbrush_old = (HBRUSH)SelectObject( hdc, hbrush2);
else
hbrush_old = (HBRUSH)SelectObject( hdc, hbrush2);
if(cr[i].sel)
{
t=i;

Ellipse( hdc,(int)(200+20*(cr[i].x-cr[i].r)), (int)(400-20*(cr[i].y+cr[i].r)), (int)(200+20*(cr[i].x+cr[i].r)), (int)(400-20*(cr[i].y-cr[i].r)) );//画圆
TextOut( hdc,(int)(200+20*cr[i].x),(int)(400-20*cr[i].y),S[i+1],2); //i,signed i+1; 并用数字标记
//TextOut( hdc,(int)(200+20*cr[i].x),(int)(400-20*cr[i].y),cr[i].r,2); //i,signed i+1; 并用数字标记
}
Sleep(750);
}
TextOut( hdc,(int)(200+20*cr[t].x),(int)(400-20*cr[t].y),S[t+1],2); //最后一个圆柱形木头放入
}

int main()//主函数
{
FILE *fp;
char filename[20];
long start; //用以计算程序运行时间
double area =0;
int i;

//printf(" 请输入数据文件:"); //读入圆柱形木头数据
//scanf("%s",filename);

if((fp=fopen("123.txt","r"))==NULL)
{
printf(" 输入文件不存在!\n ");//文件不存在则退出
exit(0);
}
start=GetTickCount();
//fscanf(fp,"%d",&columnum);
cout<<"请输入圆柱个数：";
cin>>columnum;
cout<<"集装箱的宽：";
cin>>W;
cout<<"集装箱的高：";
cin>>H;
//cout<<"集装箱的长：";
//cin>>L;
for(i=0;i<columnum;i++)
fscanf(fp,"%lf",&cr[i].r);
sort(cr,columnum); //先进行对木头的排序
Gdy(); //这个是本程序的主体函数
for(i=0;i<columnum;i++) //计算一个木头所占有的面积
if(cr[i].sel)
area += pi*cr[i].r*cr[i].r;
draw(); //画出图形
//printf(" %ld\n",columnum);
//printf("%lf\n%lf\n%lf\n",W,H);
for(i=0;i<columnum && cr[i].sel==1;i++)
{
cout<<"可装入的圆柱序号为"<<i<<endl;
}
printf(" 装入货物的面积为:%lf\n",area);
printf(" 集装箱利用率为:%lf%%\n",area/(W*H)*100);//计算集装箱利用率
printf(" 程序运行时间为:%f秒\n ",(GetTickCount()-start)/1000.0); //计算程序运行时间
getchar();
getchar();
return 0;
}

• 本文已收录于以下专栏：

## 贪心算法的运用 ——集装箱的装箱问题

• lgfeng218
• 2011年09月24日 15:02
• 3264

## 19:装箱问题（4.6算法之贪心）

19:装箱问题总时间限制: 1000ms 内存限制: 65536kB 描述 一个工厂制造的产品形状都是长方体，它们的高度都是h，长和宽都相等，一共有六个型号，他们的长宽分别为1*1, 2*2, 3...
• qq_26919935
• 2017年09月10日 20:26
• 87

## 贪心，最优装载问题

• cumt_wangxiang
• 2016年06月14日 15:18
• 248

## 关于贪心算法...

• Triose
• 2015年01月23日 21:41
• 306

## 算法java实现--贪心算法--最优装载问题

• qipanliming
• 2014年04月29日 11:14
• 4443

## 【算法导论】贪心算法之活动安排问题

• tengweitw
• 2013年11月27日 22:18
• 2265

## 2018搜狐编程题-贪心算法-二维装箱问题

• u010240385
• 2017年08月28日 22:09
• 391

## NYOJ - 14 - 会场安排问题(区间相关问题---选择不相交区间-贪心算法)

• qq_34594236
• 2016年10月19日 17:10
• 260

## 【算法题】切割木材

• xiaxzhou
• 2017年05月21日 16:59
• 516

## 贪心算法之最大不相交区间数问题

• u012736084
• 2014年02月23日 15:25
• 2056

举报原因： 您举报文章：贪心算法之木材装集装箱问题 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)