AcWing168. 生日蛋糕

在这里插入图片描述
剪枝

#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;
}
发布了38 篇原创文章 · 获赞 5 · 访问量 844

猜你喜欢

转载自blog.csdn.net/Fooooooo/article/details/104202588