[USACO 1.4.1] Packing Rectangles

[题目描述]

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=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[3]) and (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 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 ii2) 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.

你可能感兴趣的:(USACO)