注意看懂启发性剪枝
#include<iostream>
#include<cmath>
using namespace std;
#define Bottom(r) (r)*(r)//底面积
#define surArea(r,h) (2*(r)*(h))
#define Volume(r,h) ((r)*(r)*(h))//记得加括号
#define VsurArea(v,r) (2*(v)/(r))//根据体积求侧面积
#define INF 0x3f3f3f3f
int V,N,minS=INF;
int sumMinS[25],sumMinV[25];
void dfs(int iFloor,int preR,int preH,int leftv,int Sur)
{//leftv为剩余的体积,Sur为积累的表面积
if(iFloor==0)
{
if(leftv==0&&minS>Sur)minS=Sur;
return;
}
if(leftv<sumMinV[iFloor])return;//约束函数
if(Sur+sumMinS[iFloor]>minS)return;//可行性与最优性剪枝
if(preR>1&&VsurArea(leftv,preR-1)+Sur>minS)return;//限界函数,启发性剪枝
for(int r=preR-1;r>=iFloor;r--)
{
if(iFloor==N)Sur=Bottom(r);
int Hmax=1.0*(leftv-sumMinV[iFloor-1])/Bottom(r)+1;
if(Hmax>preH-1)Hmax=preH-1;
for(int h=Hmax;h>=iFloor;h--)
dfs(iFloor-1,r,h,leftv-Volume(r,h),Sur+surArea(r,h));
}
}
int main()
{
cin>>V>>N;
for(int i=1;i<=N;i++)
{//为了方便计算,另顶层为第一层
sumMinS[i]=sumMinS[i-1]+surArea(i,i);
sumMinV[i]=sumMinV[i-1]+Volume(i,i);
}
int maxR=sqrt((double)(V-sumMinV[N-1])/N+1);
int maxH=(double)(V-sumMinV[N-1])/Bottom(N)+1;
dfs(N,maxR,maxH,V,0);
if(minS==INF)cout<<0<<endl;
else cout<<minS<<endl;
return 0;
}