【Nov 1P1,爆搜之美】油滴扩展

      集训的第一天,真的好累...别的也不想说什么了,直接说下昨天的题吧。

【问题描述】
在一个长方形框子里,最多有N(
0≤N≤6)个相异的点。在其中任何一个点上放一个很小的油滴.那么
这个油滴会一直扩展,直到接触判其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油
滴。那么应该按照怎样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?
(不同的油滴不会相互融合)
【输入格式】
第一行一个整数N。
第二行为长方形边框一个顶点及其对角顶点的坐标.x,y,x’,y’,接下去N行.每行两个整数xi,yi.
表示盒子内N个点的坐标。
以上所有的整数都在[
-1000,1000]
【输出格式】
一行,一个整数,长方形盒子剩余的最小空间(结果四舍五人输出)。
【输入样例】
2
0 0 10 10
3 3
7 7
【输出样倒】
50

 

 

      首先我们一眼看到的就是数据范围,n∈[0,6]。根据这个极其敏感的数据范围判断,这道题用暴力搜索(或者是枚举)应该是没问题的(何谓敏感?参见本博“根据数据范围估算时间复杂度”一文)。所以这道题的思路很简单,只要搜索每一个油滴,记录现在所有圆的面积,枚举结束后记录最大值(如果记录的是剩余面积就是最小值)然后回溯即可。甚至有的童鞋竟然打了6重循环的枚举,简单易懂,但是也能过,而且代码极其漂亮~

      虽然思路简单,但是还要注意一些细节。首先,点的个数是0到6个,要注意0,而且不要像某些人把点看成[-1000,1000]~其次,一定要注意油滴所在位置已经被扩展过的情况。这时如果不加处理,就会出现负面积,使结果偏小。

 

参考代码:

 

1 program box;
2 var
3 n,x,y,i:longint;
4 xa,ya,xb,yb:longint;
5 xx,yy:array[1..6]of longint;
6 r:array[1..6]of double;
7 v:array[1..6]of boolean;
8 max,s:double;
9 function min(x,y:longint):longint;
10 begin
11 if x<y then exit(x)
12 else exit(y);
13 end;
14 procedure dfs(x:longint);
15 var
16 i,j:integer;
17 ro,rt:double;
18 begin
19 if x>n then
20 begin
21 if s>max then max:=s;
22 exit;
23 end;
24 for i:=1 to n do
25 if not v[i] then
26 begin
27 ro:=0; //下面是找到四条边的最小值
28 ro:=min(min(min(abs(xx[i]-xa),abs(xx[i]-xb)),abs(yy[i]-ya)),abs(yy[i]-yb));
29 for j:=1 to n do
30 if v[j] then
31 begin
32 rt:=sqrt(sqr(xx[i]-xx[j])+sqr(yy[i]-yy[j]))-r[j];
33 if(rt<ro)then ro:=rt; //找最小圆心距
34 end;
35 if ro<0 then ro:=0; //很重要,判断是否有负距离
36 v[i]:=true;
37 r[i]:=ro;
38 s:=s+pi*ro*ro;
39 dfs(x+1);
40 v[i]:=false;
41 s:=s-pi*r[i]*r[i];
42 r[i]:=0;
43 end;
44 end;
45 begin
46 assign(input,'box.in');
47 reset(input);
48 assign(output,'box.out');
49 rewrite(output);
50 readln(n);
51 readln(xa,ya,xb,yb);
52 for i:=1 to n do
53 readln(xx[i],yy[i]);
54 max:=0; s:=0;
55 fillchar(v,sizeof(v),false);
56 dfs(1);
57 writeln(round(abs(xa-xb)*abs(ya-yb)-max));
58 close(input);
59 close(output);
60 end.

 

(saltless原创,转载请注明出处)

posted on 2010-11-02 07:12  saltless  阅读(625)  评论(0编辑  收藏  举报

导航