MY*****

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.

  

posted on 2011-10-20 07:52  reflec94  阅读(411)  评论(0编辑  收藏  举报

导航