您的位置:首页 > 其它

pku1190 cake

2010-08-09 14:11 148 查看
生日蛋糕这么经典的搜索剪枝我以前都懒得做,难怪去年不给我省一……
题目大意应该都很清楚,问题就是剪枝怎么减。
首先用上下界剪枝——如果当前剩余层数所能形成的最小体积都比剩余体积大就应该减掉。同理,如果能形成的最大体积比剩余体积小也剪掉,只不过后者我懒得花时间写了,直接进行下一个剪枝。
接着呢是最优性剪枝——如果当前剩余层数所能形成的最小表面积比当前的最优解大,显然应该剪掉。
然后我们再结合一些不等式的小知识优化优化吧!
对于剩余体积 vleft 和剩余层数 dep 我们能得到如下的废话关系:



它有什么用呢?当 取得最小值时, 取得最大值,这样我们就确定了 的上界!
最后还有一个小优化!我们发现体积公式和面积公式挺有联系啊!我们尝试着约分一下就得到了这样的东西:



用不等式的传递性推导出来的这个剪枝十分给力!而且只需要短短的一句话!
当然解题报告看似简单,实际操作中是需要一定思考的!

program cake;
const
inf=200000000;
var
smin,vmin:array[0..26] of longint;
vleft,dep,r,h,ans:longint;
function getmin(a,b:longint):longint;
begin
if a<b then
exit(a)
else
exit(b);
end;
procedure calcsmin;
var
i:longint;
begin
smin[0]:=0;
for i:=1 to 25 do
smin[i]:=smin[i-1]+2*i*i;
end;
procedure calcvmin;
var
i:longint;
begin
vmin[0]:=0;
for i:=1 to 25 do
vmin[i]:=vmin[i-1]+i*i*i;
end;
procedure dfs(r,h,dep,vleft,tmp:longint);
var
i,j:longint;
begin
if dep=0 then
begin
if (tmp<ans) and (vleft=0) then
ans:=tmp;
exit;
end;
if 2*vleft div (r+1) + tmp>ans then
exit;
if smin[dep]+2*r*h>=ans then
exit;
if vmin[dep]>vleft then
exit;
for i:=r downto dep do
for j:=getmin(h,(vleft-vmin[dep-1]) div (i*i)) downto dep do
dfs(i-1,j-1,dep-1,vleft-i*i*j,tmp+2*i*j);
end;
begin
assign(input,'a.in');
reset(input);
assign(output,'a.out');
rewrite(output);
readln(vleft);
readln(dep);
calcsmin;
calcvmin;
ans:=inf;
for r:=25 downto dep do
for h:=getmin(25,(vleft-vmin[dep-1]) div (r*r)) downto dep do
begin
if vmin[dep]>vleft then
continue;
dfs(r-1,h-1,dep-1,vleft-r*r*h,r*r+2*r*h);
end;
if ans=inf then
writeln(0)
else
writeln(ans);
close(input);
close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: