如何计算在一个大矩形中,横坚能放多少个小矩形。大家介绍一下数法。(50)

  • 主题发起人 主题发起人 weibinggui
  • 开始时间 开始时间
W

weibinggui

Unregistered / Unconfirmed
GUEST, unregistred user!
一个长方形的桌面,我想在上面排一小个的长方形图标,横的,竖的都行,最后得到排得最多的那种排法。我想过过编历一个个排,但是觉得好麻烦,不知道大家有没有做过类似的题。
 
我出100现金购买这个算法。QQ:165441494
 
长方形的桌面高Y,宽X小长方形图标高b,宽a,Max((Y div a) * (X div b), (Y div b) * (X div a)) 这就是答案了
 
Y:=5; X:=6; a:=2; b:=3; 计算出来是4,但实际应该是5;
 
function CalcNum(X, Y, A, B: Integer; var Row, Col: Integer): Boolean;var tmp, MaxNum, HighLeft: Integer; N1, N2, Num: Integer; procedure DoCalc(X_, Y_: Integer); begin n1 := 0; tmp := X_ div a; if tmp=0 then exit; while n1 <= MaxNum do begin HighLeft := Y_ - Ceil(N1 / tmp) * B; n2 := (HighLeft div a) * (X_ div B); if N1 + N2 > Row + Col then begin Row := N1; Col := N2; Result := True; end; Inc(N1, tmp); end; end;begin Result := False; Row := 0; Col := 0; MaxNum := (X * Y) div (a * b); DoCalc(X,Y); DoCalc(Y,X); Result:= (Row+Col)>0;end;procedure TForm1.Button3Click(Sender: TObject);var Row, Col: Integer; //两者分别表示小单元格横向摆放和纵向摆放的个数begin if not CalcNum(5, 6, 3, 2, Row, Col) then Exit; Caption := inttostr(Row + Col);end;
 
我觉得以上算法不好,可能的话需要树型算法。这样可能比较好~!
 
修改了一下,供大家看看,可以在界面上以图形方式显示组合结果。unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DB, DBTables, ExtCtrls;type _Store = record X1, Y1: Integer; X2, Y2: Integer; X3, Y3: Integer; Z1, Z2, Z3: Boolean; Dot1, Dot2, Dot3: TPoint; end; TForm1 = class(TForm) Button3: TButton; Image1: TImage; Panel1: TPanel; procedure Button3Click(Sender: TObject); private { Private declarations } procedure DrawStore(X, Y, A, B: Integer; AStore: _Store); public { Public declarations } end;var Form1: TForm1;implementation{$R *.dfm}uses DateUtils, Math;function StoreCount(AStore: _Store): Integer;begin Result := AStore.X1 * AStore.Y1 + AStore.X2 * AStore.Y2 + AStore.X3 * AStore.Y3;end;function CalcNum(X, Y, A, B: Integer; var Store: _Store): Boolean;var MaxNum: Integer; t: _Store; procedure DoCalc(X_, Y_: Integer; _Width, _Height: Integer; StandXY, StandAB: Boolean); var tmp, HighLeft: Integer; N1, N2, Num: Integer; begin tmp := X_ div _Width; if tmp = 0 then exit; N1 := 0; while N1 <= MaxNum do begin HighLeft := Y_ - (N1 div tmp) * _Height; if HighLeft <= 0 then Break; N2 := (HighLeft div _Width) * (X_ div _Height); if (N1 + N2) > (t.X1 * t.Y1 + t.X2 * t.Y2) then begin if StandXY then begin t.X1 := tmp; t.Y1 := N1 div tmp; if t.X1=0 then t.Y1:=0; t.Dot1.X := 0; t.Dot1.Y := 0; t.X2 := (X_ div _Height); t.Y2 := (HighLeft div _Width); t.Dot2.X := 0; t.Dot2.Y := t.Y1 * _Height; end else begin t.Y1 := tmp; t.X1 := N1 div tmp; if t.Y1=0 then t.X1:=0; t.Dot1.X := 0; t.Dot1.Y := 0; t.Y2 := (X_ div _Height); t.X2 := (HighLeft div _Width); t.Dot2.Y := t.Y1 * _Height; end; t.Z1 := (StandXY = StandAB); t.Z2 := not t.Z1; end; Inc(N1, tmp); end; end; procedure Calc2(X_, Y_: Integer; _Width, _Height: Integer; StandXY, StandAB: Boolean); var I: Integer; begin for I := 0 to (X_ div _Width) do begin if X_ - I * _Width <= 0 then Continue; FillChar(t, Sizeof(Store), 0); if I > 0 then begin if StandXY then begin t.X3 := I; t.Y3 := (Y_ div _Height); t.Dot3.X := X_ - _Width * I; t.Dot3.Y := 0; end else begin t.X3 := I; t.Y3 := (Y_ div _Height); t.Dot3.X := 0; t.Dot3.Y := X_ - _Width * I; end; t.Z3 := StandXY = StandAB; end; DoCalc(X_ - I * _Width, Y_, _Width, _Height, StandXY, StandAB); DoCalc(X_ - I * _Width, Y_, _Height, _Width, StandXY, not StandAB); if StoreCount(t) > StoreCount(Store) then Store := t; end; end;begin Result := False; FillChar(Store, sizeof(Store), 0); MaxNum := (X * Y) div (a * b); Calc2(X, Y, A, B, True, True); Calc2(X, Y, B, A, True, False); Calc2(Y, X, A, B, False, True); Calc2(Y, X, B, A, False, False); Result := StoreCount(Store) > 0;end;procedure TForm1.Button3Click(Sender: TObject);var AStore: _Store; //两者分别表示小单元格横向摆放和纵向摆放的个数 X, Y, A, B: Integer; s1, s2, s3: string;begin X := 13; Y := 20; A := 3; B := 5;// X := 7; Y := 9; A := 3; B := 2; if not CalcNum(X, Y, A, B, AStore) then Exit; if AStore.Z1 then S1 := '正常摆放' else S1 := '旋转90度摆放'; if AStore.Z2 then S2 := '正常摆放' else S2 := '旋转90度摆放'; if AStore.Z3 then S3 := '正常摆放' else S3 := '旋转90度摆放'; Caption := Format('%S %d*%d + %S%d*%d + %S%d*%d =%d', [S1, AStore.X1, AStore.Y1, S2, AStore.X2, AStore.Y2, S3, AStore.X3, AStore.Y3, StoreCount(AStore)]); DrawStore(X, Y, A, B, AStore);end;procedure TForm1.DrawStore(X, Y, A, B: Integer; AStore: _Store);const Rate = 30;var _Left, _Top: Integer; procedure DrawArea(_X, _Y, _A, _B: Integer); var Row, Col: Integer; begin for Row := 1 to _Y do for Col := 1 to _X do begin image1.Canvas.Rectangle(_A * (Col - 1) * Rate + _Left + 1, (Row - 1) * _B * Rate + _Top - 2, _A * Col * Rate + _Left, Row * _B * Rate + _Top - 2); sleep(100); application.ProcessMessages; end; end;begin Panel1.Width := A * Rate; Panel1.Height := B * Rate; image1.Canvas.Brush.Color := Clwhite; image1.Width := X * Rate + 5; image1.Height := Y * Rate + 5; image1.Picture.Graphic.Width := image1.Width; image1.Picture.Graphic.Height := image1.Height; image1.Canvas.FillRect(Rect(0, 0, image1.Width, image1.Height)); image1.Canvas.Pen.Color := clred; image1.Canvas.Pen.Width := 2; image1.Canvas.Rectangle(0, 0, image1.Width - 1, image1.Height - 1); image1.Canvas.Brush.Color := clBlue; image1.Canvas.Pen.Color := ClYellow; _Left := 0; _Top := 0; if AStore.Z1 then DrawArea(AStore.X1, AStore.Y1, A, B) else DrawArea(AStore.X1, AStore.Y1, B, A); _Top := AStore.Dot2.Y * Rate; _Left := AStore.Dot2.X * Rate; if AStore.Z2 then DrawArea(AStore.X2, AStore.Y2, A, B) else DrawArea(AStore.X2, AStore.Y2, B, A); // _Top := AStore.Dot3.Y * Rate + 2; _Left := AStore.Dot3.X * Rate - 2; if AStore.Z3 then DrawArea(AStore.X3, AStore.Y3, A, B) else DrawArea(AStore.X3, AStore.Y3, B, A);end;end.
 
smlabc 的方法只适合纯的横排和竖排的情况,只能说是个粗算值。
 
关注一下,如果有好算法,再扩展一下,就可以实现计算立体空间了.(用于计算集装箱如何堆放,能放下最多货物)
 
大家期待做过这方面的同志支持一下吧。
 
呵呵,在99年时曾经试过,用当时的电脑算,如果是一个大板放一种小板,几秒种就出来了;如果是一个大板放二个小板,要几十分钟;如果是一个大板放三种小板,估计要几天才能跑出来。而且,当时并不是要求最优解,只是要求达到一种满意值(如90%)就可以了。当时是用的递归穷举法。
 
图:bykeuKFmwMc7qWbhy9bTmGyl8O5jjs-R.gif DEMO下载:http://o-c-s.weebly.com/uploads/2/0/1/3/2013949/cutpart.rar
 
最后编辑:
多人接受答案了。
 
后退
顶部