poj 1190 noi99 生日蛋糕
分析:经典剪枝。
我的稍微加了点剪枝的搜索连10000,3,这个数据都出不来结果,主要原因在于剪枝减去的太少了,而且从小到大搜索剪枝效果非常不好。后来参考了一下一个c++程序,非常快,16ms。
首先根据V=H*R*R,S=2*H*R可知2*V/S等于面积,这一面积是可能的最小面积。加上这个剪枝后非常快。
代码1:
var
ans,maxh,maxr,n,m:longint;
procedure dfs(v,h,r,deep,s:longint);
var
maxhh,maxvv,i,j:longint;
begin
if v<r*r*h*(m-deep+1) then exit;
if v<0 then exit;
if 2*r*h*(m-deep+1)+r*r>ans then exit;
if s+r*r>ans then exit;
if (v=0)and(deep<=m) then exit;
if (deep>m)and(v>0) then exit;
if (v=0)and(deep>m) then
begin
ans:=s+r*r;
exit;
end;
maxhh:=maxh;
maxvv:=maxr;
if (h>0)and(r>0) then
begin
maxhh:=trunc(v/((r+1)*(r+1)*(m-deep+1)));
maxvv:=trunc(sqrt(v/((h+1)*(m-deep+1))));
end;
for j:=r+1 to maxvv do
for i:=h+1 to maxhh do
dfs(v-j*j*i,i,j,deep+1,s+2*i*j);
end;
begin
readln(n,m);
maxr:=trunc(sqrt(n/m));
maxh:=trunc(n/m);
ans:=maxlongint;
dfs(n,0,0,1,0);
if ans=maxlongint then writeln(0)
else writeln(ans);
end.
代码2:
var
mins,minv:array[0..20] of longint;
n,m,ans,i:longint;
function min(x,y:longint):longint;
begin
if x<y then exit(x);
exit(y);
end;
procedure dfs(v,s,deep,r,h:longint);
var
i,j,hh:longint;
begin
if deep=0 then
begin
if (v=n)and(s<ans) then ans:=s;
exit;
end;
if v+minv[deep]>n then exit;
if s+mins[deep]>ans then exit;
if 2*(n-v)/r+s>=ans then exit;
for i:=r-1 downto deep do
begin
if deep=m then s:=i*i;
hh:=min(trunc((n-v-minv[deep-1])/(i*i)),h-1);
for j:=hh downto deep do
dfs(v+i*i*j,s+2*i*j,deep-1,i,j);
end;
end;
begin
readln(n,m);
for i:=1 to 20 do
begin
minv[i]:=minv[i-1]+i*i*i;
mins[i]:=mins[i-1]+2*i*i;
end;
ans:=maxlongint;
dfs(0,0,m,n+1,n+1);
if ans=maxlongint then writeln(0)
else writeln(ans);
end.
浙公网安备 33010602011771号