剪枝
#include<iostream>
#include<cmath>
using namespace std;
int minv[30],mins[30],ans=0x3f3f3f;
int h[30],r[30];
int n,m,s,v;
void dfs(int d){
if(!d){
if(v==n) ans=min(ans,s);
return ;
}
for(r[d]=min((int)sqrt(n-v),r[d+1]-1);r[d]>=d;r[d]--){//剪枝 缩小搜索范围
for (h[d] = min((int)((double)(n-v) / r[d] / r[d]), h[d+1] - 1); h[d] >= d; h[d]--){//剪枝 缩小搜索范围
if (v + minv[d-1] > n) continue;//剪枝 当前的v不能 加上 最小的后面的项之后 还要比n大
if (s + mins[d-1] > ans) continue;//剪枝 上面同理
if(2*(n-v)/r[d]+s>ans) continue;//谜一样的数学剪枝
if(d==m) s+=r[d]*r[d];
s+=2*r[d]*h[d];
v+=r[d]*r[d]*h[d];
dfs(d-1);
if(d==m) s-=r[d]*r[d];
s-=2*r[d]*h[d];
v-=r[d]*r[d]*h[d];
}
}
}
int main()
{
cin>>n>>m;
minv[0]=mins[0]=0;
for(int i=1;i<=m;i++){//每层的最小体积和表面积
minv[i]=minv[i-1]+i*i*i;//pai*(r)^2*h
mins[i]=mins[i-1]+i*i;//pai*2*r*h
}//当前体积v+最小体积大于N的话可以剪枝
h[m+1]=r[m+1]=0x3f3f3f;//13行避免d=m时出错
dfs(m);
cout<<ans<<endl;
return 0;
}