题意:传送门
题解:从下往上搜索,枚举每层的半径和高度。
整个蛋糕的表面积之和等于最下面蛋糕的上表面和所有蛋糕的侧面积,体积就是
r
∗
r
∗
h
r*r*h
r∗r∗h。
上下界剪枝:在第
d
e
p
dep
dep层时,首先枚举
r
r
r,因为
r
2
r^2
r2所占比例大于
h
h
h,总是优先枚举大的,优化搜索顺序。那么第
u
u
u层的半径和高度的范围就是:
r
∈
[
d
e
p
,
m
i
n
(
⌊
N
−
v
⌋
,
R
[
d
e
p
+
1
]
−
1
)
]
r\in [dep,min(\left \lfloor \sqrt{N-v} \right \rfloor,R[dep+1]-1)]
r∈[dep,min(⌊N−v⌋,R[dep+1]−1)]
h
∈
[
d
e
p
,
m
i
n
(
⌊
(
N
−
v
)
/
r
2
⌋
,
H
[
d
e
p
+
1
]
−
1
)
]
h\in [dep,min(\left \lfloor (N-v)/r^2 \right \rfloor,H[dep+1]-1)]
h∈[dep,min(⌊(N−v)/r2⌋,H[dep+1]−1)]
可行性剪枝:可以先预处理出从上到下前
i
i
i层的最小体积和侧面积,如果当前体积
v
v
v加上前
d
e
p
dep
dep的最小体积大于
n
n
n的话,返回,同理,如果当前表面积
s
s
s加上前
d
e
p
dep
dep的最小表面积大于
a
n
s
ans
ans的话,返回。
最优性剪枝:考虑到未来,考虑到维度与维度之间的关系,
1
∼
d
e
p
−
1
1\sim dep-1
1∼dep−1层的体积可表示为
n
−
v
=
∑
k
=
1
d
e
p
−
1
h
[
k
]
∗
r
[
k
]
2
n-v=\sum_{k=1}^{dep-1}h[k]*r[k]^2
n−v=k=1∑dep−1h[k]∗r[k]2
同理,
1
∼
d
e
p
−
1
1\sim dep-1
1∼dep−1层的表面积可表示为
2
∗
∑
k
=
1
d
e
p
−
1
h
[
k
]
∗
r
[
k
]
2*\sum_{k=1}^{dep-1}h[k]*r[k]
2∗k=1∑dep−1h[k]∗r[k]
2
∗
∑
k
=
1
d
e
p
−
1
h
[
k
]
∗
r
[
k
]
=
2
r
[
d
e
p
]
∗
∑
k
=
1
d
e
p
−
1
h
[
k
]
∗
r
[
k
]
∗
r
[
d
e
p
]
≥
2
r
[
d
e
p
]
∗
∑
k
=
1
d
e
p
−
1
h
[
k
]
∗
r
[
k
]
2
=
2
∗
(
n
−
v
)
r
[
d
e
p
]
2*\sum_{k=1}^{dep-1}h[k]*r[k]=\frac{2}{r[dep]}*\sum_{k=1}^{dep-1}h[k]*r[k]*r[dep]\ge\frac{2}{r[dep]}*\sum_{k=1}^{dep-1}h[k]*r[k]^2=\frac{2*(n-v)}{r[dep]}
2∗k=1∑dep−1h[k]∗r[k]=r[dep]2∗k=1∑dep−1h[k]∗r[k]∗r[dep]≥r[dep]2∗k=1∑dep−1h[k]∗r[k]2=r[dep]2∗(n−v)
所以当
2
∗
(
n
−
v
)
r
[
d
e
p
]
\frac{2*(n-v)}{r[dep]}
r[dep]2∗(n−v)大于搜索到的答案时,可以剪枝。
c
o
d
e
:
code:
code:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int N=25;
const int inf=1e9;
int n,m,R[N],H[N],minv[N],mins[N],ans=inf;
void dfs(int dep,int s,int v)
{
if(v+minv[dep]>n)return;
if(s+mins[dep]>=ans)return;
if(2*(n-v)/R[dep+1]+s>=ans)return;
if(!dep){if(v==n)ans=s;return;}
for(int r=min((int)sqrt(n*1.0-v),R[dep+1]-1);r>=dep;r--){
for(int h=min((n-v)/r/r,H[dep+1]-1);h>=dep;h--){
R[dep]=r;H[dep]=h;
int t=0;
if(dep==m)t=r*r;
dfs(dep-1,s+2*r*h+t,v+r*r*h);
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++){
minv[i]=minv[i-1]+i*i*i;
mins[i]=mins[i-1]+2*i*i;
}
R[m+1]=inf;H[m+1]=inf;
dfs(m,0,0);
if(ans==inf)ans=0;
cout<<ans<<endl;
return 0;
}