NOI 1999-3 生日蛋糕 解題報告
生日蛋糕
Birthday Cake
Cake.{pas|bas|c}
Cake.exe
7月17日是Mr.W的生日,ACM-THU為此要製作一個體積為Nπ的M層生日蛋糕,每層都是一個圓柱體。
設從下往上數第i(1<=i<=M)層蛋糕是半徑為Ri,高度為Hi的圓柱。當i<M時,要求Ri>Ri+1且Hi>Hi+1。
由於要在蛋糕上抹奶油,為儘可能節約經費,我們希望蛋糕外表面(最下一層的下底面除外)的面積Q最小。
令Q= Sπ
請編程對給出的N和M,找出蛋糕的製作方案(適當的Ri和Hi的值),使S最小。
(除Q外,以上所有數據皆為正整數)
輸入
有兩行,第一行為N(N<=10000),表示待制作的蛋糕的體積為Nπ;第二行為M(M<=20),表示蛋糕的層數為M。
輸出
僅一行,是一個正整數S(若無解則S=0)。
樣例輸入
100 2
樣例輸出
68
附:圓柱公式
體積V=πR2H
側面積A’=2πRH
底面積A=πR2
搜索題。
但是,樸素的搜索面臨大數據超時的危機-_-||
所以,剪枝是必要的:
最優化剪枝
k層蛋糕的最小表面積可知(h,r都為整數)
當前s可知
那麼,s+剩下層數最小表面積>=min最無需再往下搜了
可行性剪枝
k層蛋糕的最小體積minv可知
k層蛋糕的最大體積maxv可知
那麼,剩下的體積v不在minv至maxv的範圍內,即可停止搜索
最優化剪枝數據越大功力越強..^-^
於是便可以寫出程序了.
下面是我的程序,並沒有加所有的剪枝……不過AC足夠了
//NOI1999-3: CAKE
//2009-1-23: BY Ceeji
//Type : Search
program noi1999_3;
var n,m,i,j,k,l,q,max:longint;
mint,mins:array[0..20]of longint;
procedure gettijimin;
var i,j:longint;
begin
j:=0; mint[1]:=0; mint[0]:=0;
for i:=1 to m-1 do
begin
inc(j,i*i*i);
mint[i+1]:=j;
end;
end;
procedure getsmin;
var i,j:longint;
begin
j:=0; mins[1]:=0; mins[0]:=0;
for i:=1 to m-1 do
begin
inc(j,2*i*i);
mins[i+1]:=j;
end;
end;
procedure sou(i,v,s,h,r:longint); // i: ceng shu; v:ti ji; s:mian ji; h:max {height};
var j,k,l,q:longint;
begin
if (i=m+1)and(v=0)and(max>s)then
begin
max:=s; exit;
end;
if (i>m)or(v< =0) then exit;
for j:=h downto m-i+1 do
begin
for q:=r downto m-i+1 do
begin
if (i=m)and(q*q*j<>v)then continue;
if s+2*q*j+mins[m-i+1]>=max then continue;
if i<>1 then sou(i+1,v-q*q*j,s+2*q*j,j-1,q-1)
else sou(i+1,v-q*q*j,s+2*q*j+q*q,j-1,q-1);
end;
end;
end;
begin
readln(n,m);
max:=100000000;
gettijimin; getsmin;
k:=mint[m];
if n-k< =0 then begin writeln('0'); exit; end;
sou(1,n,0,trunc((n-k)/(m*m)),trunc(sqrt((n-k)/m)));
if max=100000000 then writeln('0') else writeln(max);
end.
© 轉載需附帶本文連結,依 CC BY-NC-SA 4.0 釋出。