DFS(想都不想肯定要剪枝)
递归结束条件:
- 当层数
达到 层时 - 当体积已经超过
时或得到的表面积比之前的最优值小时,更新
这道题以下几个剪枝:
- 当此时体积加上预处理的最大体积大于
时, - 当前表面积加上最优表面积大于
时,
code:
#include<stdio.h>
int min(int a,int b)
{
if(a<b)
return a;
return b;
}
int a[101],b[101],n,m,ans=0x3f3f3f3f;//a存储表面积,b存储体积
void dfs(int v,int s,int p,int r,int h)//v为已用体积,s为已有表面积,p为剩余层数,r为半径,h为高
{
int i,j,minn;
if(p==0)//蛋糕已完成
{
if(v==n&&s<ans)//判断是否符合要求并得到更优解
ans=s;//更新最优解
return ;
}
if(v+b[p-1]>n)//体积超出
return ;
if(2*(n-v)/r+s>=ans)//重点:当前的表面积+余下的侧面积>当前最优值
//侧面积S=2rh,体积V=r^2h,得到S=2V/r,注意,pai全被约掉
return ;
for(i=r-1;i>=p;i--)//枚举上一层的半径
{
if(p==m)
s=i*i;
minn=min((n-v-b[p-1])/(i*i),h-1);
for(j=minn;j>=p;j--)//枚举上一层的高
dfs(v+i*i*j,s+2*i*j,p-1,i,j);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<21;i++)
b[i]=b[i-1]+i*i*i;//第i层使用的最大体积
dfs(0,0,m,n+1,n+1);
if(ans==0x3f3f3f3f)
printf("0");
else
printf("%d",ans);
return 0;
}