请问这样如何实现?见内……(100分)

  • 主题发起人 主题发起人 youmehe
  • 开始时间 开始时间
Y

youmehe

Unregistered / Unconfirmed
GUEST, unregistred user!
现在有N个产品需要装箱,而装箱规格有二种,200/箱、300/箱,怎样把这N个产品以最小的箱数装箱。
例:若有个2000产品,要算出装箱方式为6*300+1*200=2000共装7箱,
而象4*300+4*200=2000共8箱或10*200=2000共10箱都不是最小箱数所以不考虑。

装箱时应先考虑装满的,如装不能满的,要以接近最满的来装。
例如有400个产品,应装成2*200,而不应该把300个装一箱,剩下100个又装在200的箱。
又如,若有100个产品,应该装200/箱的箱子而不该装300/箱的箱子。
换句话来说,就是考虑所装的箱子总体积应为最小的,不要浪费。

如果规格有三种,200/箱、300/箱、400/箱又如何?

能否帮忙写个算法或者过程、函数!



 
这是一个典型的箱包问题。我有一个程序,将算法用COM实现,并有客户端调用的程序。
要的话,留下EMAIL。
 
function howmany(n:integer):integer;
begin
if (n mod 300)=0 then result:=n div 300
else result:=(n div 300)+1;
end;

若为200,300,400…… 只需修改最大的那个就行了
 
补充,设最大致如400,最小指如200,如果余数小于最小指,取最小值,否则递增

那样的话,如果是700 就是 2*300+1*200 需要你逐个判断
 
function GetBoxNumber(n:Integer):Integer;
begin
Result:=n div 400;
if n mod 400>0 then
Inc(Result);
end;
procedure Fit(n:Integer);
var
i,num:Integer;
a:array[1..3]of Integer;
begin
num:=GetBoxNumber(n);
Form1.Caption:='共需'+IntToStr(num)+'个箱子。分别为:';
if n>500 then //当n>500时有必要使用规格为400的箱子
begin
a[3]:=(n-100) div 400;
Dec(n,a[3]*400);
end
else
a[3]:=0;
//此时n<=500
a[1]:=0;
a[2]:=0;
if n>400 then //如果大于400,则用300和200的
begin
Inc(a[1]);
Inc(a[2]);
end
else if n>300 then
Inc(a[3])
else if n>200 then
Inc(a[2])
else
Inc(a[1]);
for i:=1 to 3 do
Form1.Caption:=Form1.Caption+IntToStr(a)+' ';
end;
 
我也写一个:

procedure TForm1.Button1Click(Sender: TObject);
var
a2,a3,a4:integer;
begin
GetBoxCount(StrToInt(Edit1.Text),a2,a3,a4);
Label1.Caption:=IntToStr(a2);
Label2.Caption:=IntToStr(a3);
Label3.Caption:=IntToStr(a4);
end;

procedure TForm1.GetBoxCount(product: integer
var Box2, Box3, Box4: integer);
begin
Box2:=0;
Box3:=0;
Box4:=0;
while product>0 do
case product of
1..200: begin
Box2:=Box2+1;
product:=0;
end;
201..300: begin
Box3:=Box3+1;
product:=0;
end;
301..400: begin
Box4:=Box4+1;
product:=0;
end;
401..500: begin
Box2:=Box2+1;
Box3:=Box3+1;
product:=0;
end;
else begin
Box4:=Box4+1;
product:=product-400;
end;
end;
end;
 
不好意思,上面的算法没考虑n=0的情况,修改如下:
else
Inc(a[1]);
改为:
else if n>0 then
Inc(a[1]);

箱子的规格为200,300时的算法:
if n>400 then //当n>400时有必要使用规格为300的箱子
begin
a[2]:=(n-100) div 300;
Dec(n,a[2]*300);
end
else
a[2]:=0;
//此时n<=400
a[1]:=0;
if n>300 then //如果大于300,则用两个200的
Inc(a[1],2)
else if n>200 then
Inc(a[2])
else if n>0 then
Inc(a[1]);
 
to
wind_cloudy
我的email:jiao_he@sina.com
 
To
creation-zy

你的过程有点小问题,当产品数大于或等于900后,每增加400都会出现一次装箱错误,即当数量为900、1300、1700、2100、2400……装400的箱数会多1箱,而装300的箱数会小1箱。
按规律有个笨办法解决:
procedure TForm1.Fit(n:Integer);
var
i,num,m:Integer;
a:array[1..3]of Integer;
begin
m:=n;

{
……
……
原来代码……
}


//增加的*********************************

if ( m>500 ) and (( m mod 400 ) = 100 ) then
begin
Dec(a[3]);
Inc(a[2]);
end


//***************************************

for i:=1 to 3 do
Form1.Caption:=Form1.Caption+IntToStr(a)+' ';

end;
 
以上方法都有个缺点,装箱规格和规格的种类都是已知的,但在实际应用中就不那么灵活,
假如过一段时期后装箱规格或规格的种类出现更改的话,到时只有拿程序重新改一遍了,这可麻烦了。
能否使装箱规格和规格的种类可以根据实际需要动态设置呢,但这样程序难度就大多了,又如何实现呢?
 
算法的问题,晚上回家想想,:)
 
tinytao的方法相对简洁!但如果能实现动态设置装箱规格和规格种类那更完美了。
如可以解决前一条贴子说的能动态设置,再奉送100分。
 
哎呀!我没想到还有这种情况,真是对不起!非常感谢您的指正!我有一个更简单的解决方案:
a[3]:=(n-101) div 400
//避开n=m*400+500的情况
什么都不用加。OK!

>tinytao的方法相对简洁!
不懂。我的算法无论从功能、行数还是执行效率,都有过之而无不及。tinytao的算法在处理n非常大的
时候效率不高,因为这一句:else begin Box4:=Box4+1
product:=product-400
end
要被多次执行,
而我的顶多只要执行一次就能够将n转移到0-500的区间里去了。tingtao用的case语句和我的if then else
在功能上完全是一样的(当然,如果您觉得case语句就是好,我也没辙)。

>使装箱规格和规格的种类可以根据实际需要动态设置
这个问题基本上比较麻烦。一旦箱子的种类超过4种,最优组合的取得将会变得非常复杂。这个问题和
《数据结构与算法》中的“装箱问题”有些相似,但并不完全一样。根据我的分析,此问题似乎可以看成
货物的体积都为1的装箱问题,看一看《数据结构与算法》,里面有此问题的C语言代码。
 
多人接受答案了。
 
后退
顶部