不知道为什么,这道题目做不出来,心里总是不踏实,脑子里总有一个心事在
那里,如果毕业后老板就让我写一个这样的东西,我能回答说,不会吗?
要找到一个完美的组合,还是有难度的,而且不是唯一的。
经过一个一段时间的考虑,写了一个自己比较满意的算法,
效率是非常高的,至于空间就大了一点了。因为很难把意想
表达出来,所以还是把它贴出来了,肯定还有值得改进的地方
(如:Bakgood()这个过程),只是给大家做一个参考,也许rechild还是不满意,
希望你能把找到的那个 GLarray[][] 数组贴出来,我再来改进算法。
我用不同GLarray数组,做了不少测试,分解过程还是可以的。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo2: TMemo;
procedure Button1Click(Sender: TObject);
procedure pro(sender:tobject;L:integer);
function IsFirst(sender: Tobject;currentPos:integer):boolean;
//判断当前位置是不是要分割的最长的一个。
function prvIsNull(sender:Tobject;Pos:integer):boolean;
procedure screenCtoB(sender:Tobject);
procedure CtoB(sender:Tobject;Pos,size:integer);
procedure Bakgood(sender:Tobject);
function proBYushu():integer;
procedure recover(i:integer);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
type
TGLrecored=record
GLleng:integer;
GLcount:integer;
end;
var
L:integer;
//这个L就是你问题中的那个L
GLarray:array[1..10] of TGLrecored;
//我们假设所有的钢管的类型,数量都放在这个数组中;
resultarray :array of array of integer;
a,b,Bak:array[1..10]of integer;
//a,b为临时数组,bak 为上
minL,Lcount,BakLcountPos,BakYuShu:integer;
AItag:array[1..10]of boolean;
c:array[1..50,1..10]of integer;
//我们把每次找到的最佳组合放在C中。最后筛选出一个我们认为比较好的放在B中。因为也不一定是正确的组合
cCount:integer;
//c数组中的有效行的计数器
implementation
{$R *.DFM}
procedure TForm1.Bakgood(sender: Tobject);
var
BYuShu,i,j,k,s1,s2,n:integer;
begin
screenctob(sender);
i:=10;
j:=10;
while (bak=0) and (i>0) do
dec(i);
while (b[j]=0) and (j>0)do
dec(j);
if (i=0) or (j>=i) then
begin
n:=10;
//N为要分割钢管的种类的大小。
BYushu:=probyushu;
//for i:=1 to 10do
// if b<>0 then
BYuShu:=BYuShu-Glarray.GLleng*b;
if BYuShu=BakYuShu then
begin
for i:=1 to 10do
if b<>0 then
break;
for j:=1 to 10do
if Bak[j]<>0 then
break;
if i=j then
begin
s1:=0;
s2:=0;
while (s1=s2) and (n<>0)do
begin
s1:=0;
s2:=0;
for k:=1 to n div 2do
begin
s1:=s1+bak[k];
s2:=s2+b[k];
end;
n:=n div 2;
end;
if s1>s2 then
begin
bak:=b;
BakLcountPos:=Lcount;
end;
end;
if i>j then
begin
Bak:=b;
BakLcountPos:=Lcount;
end;
end;
if BYuShu<BakYuShu then
begin
bak:=b;
BakYuShu:=BYuShu;
BakLcountPos:=Lcount;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var i,j,k:integer;
Scount:integer;//longword;
s:string;
begin
GLarray[1].GLleng:=5;
GLarray[1].GLcount:=12;
GLarray[2].GLleng:= 11;
GLarray[2].GLcount:=12;
GLarray[3].GLleng:=24;
GLarray[3].GLcount:=12;
GLarray[4].GLleng:=27;
GLarray[4].GLcount:=12;
GLarray[5].GLleng:=29;
GLarray[5].GLcount:=12;
GLarray[6].GLleng:=33;
GLarray[6].GLcount:=12;
GLarray[7].GLleng:=35;
GLarray[7].GLcount:=12;
GLarray[8].GLleng:=36;
GLarray[8].GLcount:=12;
GLarray[9].GLleng:=47;
GLarray[9].GLcount:=0;
GLarray[10].GLleng:=53;
GLarray[10].GLcount:=0;
{必须要先对GLayyay这个数组按GLleng排序,我们假设已经排过了。}
L:=100;
//这个L就是你问题中的那个L
scount:=0;
for j:=1 to 10do
scount:=scount+GLarray[j].GLleng*glarray[j].GLcount;
k:=scount div L *2;
setlength(resultarray,k,11);
BakYuShu:=L;
LCount:=0;
j:=1;
while j<>0do
begin
inc(LCount);
minL:=L;//GLarray[1].GLleng;
for j:=1 to 10do
begin
AItag[j]:=true;
a[j]:=0;
end ;
cCount:=0;
pro(sender,L);
//开始分割一个L型号的管子 。结果放在C数组中
screenCtoB(sender);
//筛选C数组中的组合->B中 。
i:=1;
j:=0;
while i<=10do
begin
resultarray[LCount]:=b;
GLarray.GLcount:=GLarray.GLcount-b;
j:=j+GLarray.GLcount;
inc(i);
end;
if (probyushu>GLarray[1].GLleng) and (j>0)then
begin
recover(Lcount);
Lcount:=BakLcountPos;
j:=0;
for i:=1 to 10do
begin
resultarray[LCount]:=bak;
GLarray.GLcount:=GLarray.GLcount-bak;
j:=j+GLarray.GLcount;
end;
end;
end;
for i:=1 to Lcountdo
begin
for j:=1 to 10do
begin
s:=s+inttostr(resultarray[j])+' ';
end;
memo2.Lines.Add(s);
s:='';
end;
ShowMessage('经过计算至少需要:'+inttostr(LCount)+'个L型号的管子');
resultarray:=nil;
end;
procedure TForm1.CtoB(sender: Tobject;
Pos,Size: integer);
//把C数组中的Pos行放入B中
var
i:integer;
begin
for i:=1 to Sizedo
b:=c[pos];
end;
function TForm1.IsFirst(sender: Tobject;currentPos:integer): boolean;
var
i :integer;
begin
result:=false;
i:=10;
while i>currentPosdo
if a<>0 then
break
else
dec(i);
if i=currentPos then
result:=true;
end;
procedure TForm1.pro(sender: tobject;
L: integer);
var
i,j,k:integer;
begin
i:=10;
while ((i>0) and (GLarray.GLcount=0)) or (not (AItag)) or (L<GLarray.GLleng) do
dec(i);
if i>0 then
begin
a:=L div Glarray.GLleng;
if a>GLarray.GLcount then
a:=GLarray.GLcount;
j:=a;
while j>=0do
begin
if (j=0) and (IsFirst(sender,i)) and (not prvISnull(sender,i)) then
break;
AItag:=false;
a:=j;
if L-GLarray.GLleng*j=Minl then
begin
if cCount<50 then
begin
for k:=1 to 10do
c[cCount+1][k]:=a[k];
inc(cCount);
end;
end;
if L-GLarray.GLleng*j<Minl then
begin
if cCount>0 then
bakgood(sender);
for k:=1 to 10do
c[1][k]:=a[k];
cCount:=1;
Minl:=L-GLarray.GLleng*j;
end;
IF i<>1 then
pro(sender,L-GLarray.GLleng*j);
dec(j);
for k:=1 to ido
AItag[k]:=true;
end;
end;
end;
function TForm1.proBYushu: integer;
var
i,n:integer;
begin
n:=L;
for i:=1 to 10do
if b<>0 then
n:=n-Glarray.GLleng*b;
result:=n;
end;
function TForm1.prvISnull(sender: Tobject;
Pos: integer): boolean;
var
i:integer;
begin
result:=false;
i:=Pos-1;
while i>=1do
begin
if c[1]<>0 then
break;
dec(i);
end;
if i=0 then
result:=true;
end;
procedure TForm1.recover(i: integer);
var
j,k:integer;
begin
for j:=BakLcountPos to ido
for k:=1 to 10do
if resultarray[j][k]<>0 then
GLarray[k].GLcount:=Glarray[k].GLcount+resultarray[j][k];
BakYuShu:=100;
end;
procedure TForm1.screenCtoB(sender: Tobject);
var
i,j,k,p,s1,s2,n:integer;
begin
p:=0;
n:=10;
for i:=1 to cCountdo
begin
for j:=1 to 10do
if c[j]<>0 then
break;
if j=p then
begin
s1:=0;
s2:=0;
while (s1=s2) and (n<>0)do
begin
s1:=0;
s2:=0;
for k:=1 to n div 2do
begin
s1:=s1+c[k];
s2:=s2+b[k];
end;
n:=n div 2;
end;
if s1<s2 then
Ctob(sender,i,10);
end;
if j>p then
begin
CtoB(sender,i,10);
p:=j;
end;
end;
end;
end.