很容易想到dp,f[i,j,k]表示到第i根木棒所组成三条边中两条边长为j,k是否存在

之后找所有满足三角形形成条件的三条边,然后找最大;

但:

如果你朴素的写,很有可能超时,事实上,只要加一些常数优化,就能卡过去

 1 var a,s:array[0..50] of longint;
 2     f:array[0..1,0..2000,0..2000] of boolean;
 3     i,j,k,k1,k2,n,l:longint;
 4     ans,p,t:double;
 5 begin
 6   readln(n);
 7   for i:=1 to n do
 8   begin
 9     readln(a[i]);
10     s[i]:=s[i-1]+a[i];
11   end;
12   f[0,0,0]:=true;
13   k1:=1;
14   k2:=0;
15   for i:=1 to n do
16   begin
17     k1:=k1 xor 1;
18     k2:=k2 xor 1;
19     for j:=0 to s[i] do
20     begin
21       l:=min(j,s[i]-j);
22       for k:=0 to l do //常数优化1
23       begin
24         if j-a[i]>=0 then f[k2,j,k]:=f[k2,j,k] or f[k1,j-a[i],k];
25         if k-a[i]>=0 then f[k2,j,k]:=f[k2,j,k] or f[k1,j,k-a[i]];
26         if s[i]-j-k-a[i]>=0 then f[k2,j,k]:=f[k2,j,k] or f[k1,j,k];
27       end;
28     end;
29   end;
30   ans:=0;
31   for i:=1 to s[n]-2 do
32     for j:=(s[n] shr 1)+1-j to min(s[n]-j-1,j) do   //常数优化2:满足三角形
33       if f[k2,i,j] and (s[n]-i-j>0) then
34       begin
35         k:=s[n]-i-j;
36         if (j>=i+k) or (k>=i+j) or (i>=j+k) then continue;
37         t:=(k+i+j)/2;
38         p:=sqrt(t*(t-i)*(t-j)*(t-k));
39         ans:=max(ans,p);
40       end;
41   if ans=0 then writeln(-1) else writeln(trunc(ans*100));
42 end.
View Code

事实上在OI中,多加一些常数优化往往有意想不到的效果!

 

posted on 2014-02-10 14:37  acphile  阅读(157)  评论(0编辑  收藏  举报