这个该如何用递补归快速求出解来呢?(100分)

N

noall

Unregistered / Unconfirmed
GUEST, unregistred user!
有一堆长度为90(可变)的木材A,而需要一批长度分别
40 ,25,30,20(这一组数据可增,可减,变化的)的木材。
请问A类木材有几种分割法呢?
所以的分割方法列表如下:如何用递归法求出?(我想应该有用递归的吧)

定长(90)

40 25 30 20

1 2 0 0 0 一根a只能分二根40
2 1 2 0 0 一根a可分一根40,二根25
3 1 1 0 1 a 可分一根40 一根25 一根20的
4 0 3 0 0 ...
5 0 2 1 0 ...
6 0 2 0 2 ...
7 0 1 2 0 ...
8 0 1 1 1 ...
9 0 0 3 0 ...
10 0 0 2 1 ...
11 0 0 1 3 ...
12 0 0 0 4 ...
 
还问哪.这是求最优解的代码.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
const
MaxMaterialNum = 10;
MaxOrderNum = 40;
type
TUsedMaterial = record
MaterialNo: Integer;
UnUsedSize: Integer;
Orders: set of Byte
end;

TOrder = record
Size: Integer;
MaxWaster: Integer;
MaterialNo: Integer
end;

TNode = record
d: Integer;
UsedMaterial: array [1..MaxOrderNum] of TUsedMaterial;
UsedMaterialNum: Integer;
AllUnUsedSize: Integer
end;

var
Material: array [1..MaxMaterialNum] of Integer;
MaterialNum: Integer;
Order: array [1..MaxOrderNum] of TOrder;
OrderNum: Integer;
Stack: array [1..MaxOrderNum+1] of TNode;
Top: Integer;
NewNode: TNode;
do
ne: Boolean;
Better: TNode;
BestWaster: array [1..MaxOrderNum] of Integer;
WorstWaster: array [0..MaxOrderNum] of Integer;
procedure PackMaterial;
var
i, j: Integer;
t: Integer;
begin
i:=1;
while i<MaterialNumdo
begin
j:=i+1;
while j<=MaterialNumdo
begin
if Material=Material[j] then
begin
Material[j]:=Material[MaterialNum];
Dec(MaterialNum)
end;
Inc(j)
end;
Inc(i)
end;

for i:=1 to MaterialNum-1do
for j:=i+1 to MaterialNumdo
if Material>Material[j] then
begin
t:=Material;
Material:=Material[j];
Material[j]:=t
end
end;

procedure InitOrders;
var
i, j: Integer;
t: TOrder;
begin
for i:=1 to OrderNumdo
begin
j:=1;
while (Material[j]<Order.Size) and (j<=MaterialNum)do
Inc(j);
if j>MaterialNum then
begin
WriteLn('Not Found!');
ReadLn;
Halt
end;
Order.MaxWaster:=Material[j]-Order.Size;
Order.MaterialNo:=j
end;

for i:=1 to OrderNum-1do
for j:=i+1 to OrderNumdo
if Order.MaxWaster<Order[j].MaxWaster then
begin
t:=Order;
Order:=Order[j];
Order[j]:=t
end
end;

procedure InitBetter;
var
i, j: Integer;
do
ne: Boolean;
begin
BestWaster[1]:=0;
for i:=2 to OrderNumdo
BestWaster[1]:=BestWaster[1]+Order.Size;
for i:=2 to OrderNumdo
BestWaster:=BestWaster[i-1]-Order.Size;
Better.UsedMaterialNum:=1;
Better.UsedMaterial[1].MaterialNo:=Order[OrderNum].MaterialNo;
Better.UsedMaterial[1].UnUsedSize:=Order[OrderNum].MaxWaster;
Better.UsedMaterial[1].Orders:=[OrderNum];
Better.AllUnUsedSize:=Order[OrderNum].MaxWaster;
WorstWaster[OrderNum-1]:=Better.AllUnUsedSize;
for i:=OrderNum-1do
wnto 1do
begin
j:=1;
do
ne:=False;
while (j<=Better.UsedMaterialNum) and (notdo
ne)do
begin
if Order.Size<=Better.UsedMaterial[j].UnUsedSize then
begin
Better.UsedMaterial[j].UnUsedSize:=Better.UsedMaterial[j].UnUsedSize
-Order.Size;
Better.UsedMaterial[j].Orders:=Better.UsedMaterial[j].Orders+;
Better.AllUnUsedSize:=Better.AllUnUsedSize-Order.Size;
do
ne:=True
end
else
Inc(j)
end;
if notdo
ne then
begin
Inc(Better.UsedMaterialNum);
Better.UsedMaterial[Better.UsedMaterialNum].MaterialNo:=Order.MaterialNo;
Better.UsedMaterial[Better.UsedMaterialNum].UnUsedSize:=Order.MaxWaster;
Better.UsedMaterial[Better.UsedMaterialNum].Orders:=;
Better.AllUnUsedSize:=Better.AllUnUsedSize+Order.MaxWaster
end;
WorstWaster[i-1]:=Better.AllUnUsedSize
end
end;

procedure Init;
var
i: Integer;
begin
Write('Input Material Num: ');
ReadLn(MaterialNum);
for i:=1 to MaterialNumdo
begin
Write('Input Material[', i, '] Size:');
ReadLn(Material)
end;

Write('Input Order Num: ');
ReadLn(OrderNum);
for i:=1 to OrderNumdo
begin
Write('Input Order[', i, '] Size:');
ReadLn(Order.Size)
end;

PackMaterial;
InitOrders;
Top:=1;
with Stack[Top]do
begin
d:=0;
FillChar(UsedMaterial, SizeOf(UsedMaterial), 0);
UsedMaterialNum:=0;
AllUnUsedSize:=0
end;

InitBetter
end;

procedure Print(Node: TNode);
var
i, j: Integer;
begin
for i:=1 to Node.UsedMaterialNumdo
begin
Write(Material[Node.UsedMaterial.MaterialNo], ' :');
for j:=1 to OrderNumdo
if (j in Node.UsedMaterial.Orders) then
Write(' ', Order[j].Size);
WriteLn(' UnUsed Size=', Node.UsedMaterial.UnUsedSize)
end;
WriteLn('All UnUsed Size=', Node.AllUnUsedSize)
end;

begin
Init;
while Top>0do
begin
while Stack[Top].d<Stack[Top].UsedMaterialNum+MaterialNumdo
begin
do
ne:=False;
Inc(Stack[Top].d);
NewNode:=Stack[Top];
if NewNode.d<=NewNode.UsedMaterialNum then
begin
if Order[Top].Size<=NewNode.UsedMaterial[NewNode.d].UnUsedSize then
begin
NewNode.UsedMaterial[NewNode.d].UnUsedSize:=
NewNode.UsedMaterial[NewNode.d].UnUsedSize-Order[Top].Size;
NewNode.UsedMaterial[NewNode.d].Orders:=
NewNode.UsedMaterial[NewNode.d].Orders+[Top];
NewNode.AllUnUsedSize:=NewNode.AllUnUsedSize-Order[Top].Size;
do
ne:=True
end
end
else
begin
if Order[Top].Size<=Material[NewNode.d-NewNode.UsedMaterialNum] then
begin
Inc(NewNode.UsedMaterialNum);
NewNode.UsedMaterial[NewNode.UsedMaterialNum].MaterialNo:=
NewNode.d-NewNode.UsedMaterialNum+1;
NewNode.UsedMaterial[NewNode.UsedMaterialNum].UnUsedSize:=
Material[NewNode.UsedMaterial[NewNode.UsedMaterialNum].MaterialNo]
-Order[Top].Size;
NewNode.UsedMaterial[NewNode.UsedMaterialNum].Orders:=[Top];
NewNode.AllUnUsedSize:=NewNode.AllUnUsedSize
+NewNode.UsedMaterial[NewNode.UsedMaterialNum].UnUsedSize;
do
ne:=True
end
end;
ifdo
ne then
begin

if Top=OrderNum then
begin
if NewNode.AllUnUsedSize<=Better.AllUnUsedSize then
Better:=NewNode
end
else
if ((NewNode.AllUnUsedSize-BestWaster[Top])<=Better.AllUnUsedSize) and (Top<OrderNum) then
begin
if (NewNode.AllUnUsedSize+WorstWaster[Top])<Better.AllUnUsedSize then
begin
Better:=NewNode;
Better.AllUnUsedSize:=Better.AllUnUsedSize+WorstWaster[Top]
end;
Inc(Top);
Stack[Top]:=NewNode;
Stack[Top].d:=0
end
end
end;
Dec(Top)
end;
if Better.UsedMaterialNum=0 then
WriteLn('Not Found!')
else
Print(Better);
ReadLn
end.
 
运行上面的程序时,如何输入所输的根数呢?
就是:1根40,2根25,2根30 2根15,这个根数如何输入呢???
QQ:931486
谢谢!!!
 
第一个输入原料数量,为1
第二个输入原料长度,为90
第三个输入的材料数量,为7
第4个输40
第5,6输25
7,8输30
9,10输15
 
果然。可以。
谢谢。
再问个苛刻问题:这些单根求出的有没有办法汇总呢,
就是说分割方法一样的根数总共有多少根?
 
听不懂.
 
第一个输入原料数量,为1
第二个输入原料长度,为90
第三个输入的材料数量,为7 如果这个地方输入的是14
再输入2个40,4个30,4个25,4个15

这时得到的是四根:
40 25 25 分割法a
40 25 25
30 30 15 15 分割法b
30 30 15 15
我的意思 分割法a共用了多少次(2根),分割法b用了多少次(2根)
 
MaxMaterialNum = 10;//最大的材料种类?
MaxOrderNum = 40;//最大的根数??
这二个常量起什么作用?
 
这个你看看输出结果不就知道了吗?
maxMaterialNum是最大的原料种类,对你的运用没任何影响.
MaxOrderNum是最大的材料数量,可以改大.
 
当我将
MaxOrderNum改为以万为单位时,
那所统计分割方法可能又要耗时多多?所以想能否在算未法中也一并统计呢?
 
以万为单位时肯定照不住,一定得换算法.
输出总数量只要改一句话.
procedure Print(Node: TNode);
var
i, j: Integer;
begin
//就加这一句
WriteLn(Node.UsedMaterialNum);
for i:=1 to Node.UsedMaterialNumdo
begin
Write(Material[Node.UsedMaterial.MaterialNo], ' :');
for j:=1 to OrderNumdo
if (j in Node.UsedMaterial.Orders) then
Write(' ', Order[j].Size);
WriteLn(' UnUsed Size=', Node.UsedMaterial.UnUsedSize)
end;
WriteLn('All UnUsed Size=', Node.AllUnUsedSize)
end;
 
有什么办法可以提高速度呢??
刚才试了一组数组
定长还是90,
但数据有28个:
4根40
8根25
8根20
8根15
等了5分钟还没出结果。
如果上面的数量减半只需要3秒。
如果再减半基本上一点就出来。。。。。。

 
呵呵,这个算法本是对有多种原料设计的.
你的需求是只有一种原料,完全可以设计个快一点的算法.
 
呜呜,,,
LeeChange:应该如何修改会更好呢???
 
彻底换.
 
倒。
给讲讲思路先。。。
 
有好方法吗???
 
呵呵,性子很急嘛,这两天不是还在放假嘛.
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
927
SUNSTONE的Delphi笔记
S
D
回复
0
查看
739
DelphiTeacher的专栏
D
D
回复
0
查看
742
DelphiTeacher的专栏
D
D
回复
0
查看
590
DelphiTeacher的专栏
D
顶部