[題目描述]
Packing Rectangles
鋪放矩形塊
IOI 95
給定4個矩形塊,找出一個最小的封閉矩形將這4個矩形塊放入,但不得相互重疊。所謂最小矩形指該矩形面積最小。
所有4個矩形塊的邊都與封閉矩形的邊相平行,圖1示出了鋪放4個矩形塊的6種方案。這6種方案僅只是可能的基本鋪放方案。因爲其它方案能由基本方案通過旋轉和鏡像反射得到。
可能存在滿足條件且有着同樣面積的各種不同的封閉矩形,你應該輸出所有這些封閉矩形的邊長。
PROGRAM NAME: packrec
INPUT FORMAT
共有4行。每一行用兩個正整數來表示一個給定的矩形塊的兩個邊長。矩形塊的每條邊的邊長範圍最小是1,最大是50。
SAMPLE INPUT (file packrec.in)
1 2
2 3
3 4
4 5
OUTPUT FORMAT
總行數爲解的總數加1。第一行是一個整數,代表封閉矩形的最小面積(子任務A)。接下來的每一行都表示一個解,由數P和數Q來表示,並且P≤Q(子任務B)。這些行必須根據P的大小按升序排列,P小的行在前,大的在後。且所有行都應是不同的。
SAMPLE OUTPUT (file packrec.out)
40
4 10
5 8
[解題思路]
IOI 的神級題啊、 Orz...
看數據範圍應該是搜,但具體方法想了好久都沒有思路。枚舉長寬吧,檢驗複雜度過高,並且不好實現,要用棧記錄可以放的點;迭代枚舉最小面積吧,同樣還是要枚舉長寬......
絕望之中百度了下,發現神犇的Bo,觀摩入口在這裏。
其實就是題目中給定的幾種基本情況(看題的時候根本沒注意... = =、),枚舉4個矩形的排列順序,再枚舉每一種擺放方法,記錄最優解,排序輸出即可。
130+行的代碼,觀Bo之後,自己重新手枚一遍的結果,一紙的僞代碼照着敲的...
[Code]
{
ID: zane2951
PROG: packrec
LANG: PASCAL
}
program packrec;
var
x,y,q,l,h:array[0..5] of longint;
xx,yy:array[0..1111] of longint;
f:array[0..201,0..201] of boolean;
ans,top,i,i1,i2,i3,i4:longint;
//----------max------------
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
//-----------up------------
procedure up(hh,ll:longint);
var
tmp:longint;
begin
if ll<hh then begin tmp:=ll; ll:=hh; hh:=tmp; end;
if hh*ll<=ans then
if hh*ll<ans then
begin
ans:=hh*ll;
top:=1;
xx[top]:=hh;
yy[top]:=ll;
f[hh,ll]:=true;
f[ll,hh]:=true;
end
else
if not f[hh,ll] then
begin
inc(top);
xx[top]:=hh;
yy[top]:=ll;
f[hh,ll]:=true;
f[ll,hh]:=true;
end;
end;
//---------check-----------
procedure check;
var
hh,ll:longint;
begin
hh:=max(h[1],max(h[2],max(h[3],h[4])));
ll:=l[1]+l[2]+l[3]+l[4];
up(hh,ll);
hh:=max(h[1],max(h[2],h[3]))+h[4];
ll:=max(l[4],l[1]+l[2]+l[3]);
up(hh,ll);
hh:=max(h[3],max(h[1]+h[4],h[2]+h[4]));
ll:=max(l[3]+l[4],l[1]+l[2]+l[3]);
up(hh,ll);
hh:=max(h[1],max(h[4],h[2]+h[3]));
ll:=max(l[1]+l[2]+l[4],l[1]+l[4]+l[3]);
up(hh,ll);
hh:=max(h[1]+h[3],h[2]+h[4]);
if h[3]>=h[2]+h[4] then ll:=max(l[1],l[3]+max(l[2],l[4]))
else
if (h[3]>h[4]) and (h[3]<h[2]+h[4]) then ll:=max(l[1]+l[2],max(l[2]+l[3],l[3]+l[4]))
else
if (h[4]>h[3]) and (h[4]<h[1]+h[3]) then ll:=max(l[1]+l[2],max(l[1]+l[4],l[3]+l[4]))
else
if h[4]>=h[1]+h[3] then ll:=max(l[2],max(l[1]+l[4],l[3]+l[4]))
else ll:=max(l[1]+l[2],l[3]+l[4]);
up(hh,ll);
end;
//----------run------------
procedure run(dp:longint);
begin
if dp>4 then
begin
check;
exit;
end;
l[dp]:=x[q[dp]]; h[dp]:=y[q[dp]]; run(dp+1);
l[dp]:=y[q[dp]]; h[dp]:=x[q[dp]]; run(dp+1);
end;
//-----------qs------------
procedure qs(s,t:longint);
var
i,j,ce,tmp:longint;
begin
i:=s; j:=t; ce:=xx[(i+j)>>1];
repeat
while xx[i]<ce do inc(i);
while xx[j]>ce do dec(j);
if i<=j then
begin
tmp:=xx[i]; xx[i]:=xx[j]; xx[j]:=tmp;
tmp:=yy[i]; yy[i]:=yy[j]; yy[j]:=tmp;
inc(i); dec(j);
end;
until i>j;
if i<t then qs(i,t); if s<j then qs(s,j);
end;
//----------main-----------
begin
assign(input,'packrec.in'); reset(input);
assign(output,'packrec.out'); rewrite(output);
for i:=1 to 4 do readln(x[i],y[i]);
ans:=maxlongint;
for i1:=1 to 4 do
for i2:=1 to 4 do
for i3:=1 to 4 do
for i4:=1 to 4 do
if (i1<>i2) and (i1<>i3) and (i1<>i4) and
(i2<>i3) and (i2<>i4) and (i3<>i4) then
begin
q[1]:=i1; q[2]:=i2;
q[3]:=i3; q[4]:=i4;
run(1);
end;
qs(1,top);
writeln(ans);
for i:=1 to top do writeln(xx[i],'':1,yy[i]);
close(input); close(output);
end.