生日蛋糕

生日蛋糕


赤果果的搜索题。
恩,好题。
对于剪枝来说,我们可以使用最优情况进行剪枝,即是:使用最优情况+现在的情况与得到的答案进行比较
类似于估价函数的简单实现

然后对于这个题,我们可以寻找体积与面积之间的联系,利用不等式进行剪枝

$S_{ ext{剩余}}=sum^{m}_{i= ext{剩余层数}} ~~~~~R_i cdot 2 cdot H_i $
(V_{ ext{剩余}}=sum^{m}_{i= ext{剩余层数}}~~~~~R_I^2 cdot H_i)
对于(V_{ ext{剩余}}),有(frac{V_{ ext{剩余}} cdot 2}{R_{ ext{当前层}}} <= S_{ ext{剩余}})

所以,我们可以根据上述式子进行剪枝

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using std::min;
const int M=16;
int n,m;
int r[M],S[M],V[M],h[M];
int ans=0x7fffffff;
void dfs(int Vol,int sum,int now,int R,int H)//Vol:当前体积,sum:当前面积,now当前层数(自上而下),R:当层的最大半径,H同理
{
    if(now==0)//终止条件
    {
        if(Vol==n)
            ans=min(ans,sum);
        return ;
    }
    if(sum+S[now]>=ans) return ;//最优情况剪枝
    if(Vol+V[now]>n)   return ;//最优情况剪枝
    if(2*(n-Vol)/R+sum>=ans)  return ;//根据两者之间的关系剪枝
    for(int i=R;i>=r[now];i--)
    {
        if(now==m)  sum=i*i;//如果是底层,加上顶部面积
        int NxtH=min(H,(n-Vol-V[now-1])/(i*i));//根据上面蛋糕的最优情况,计算当前层的最高的高度
        for(int j=NxtH;j>=h[now];j--)//枚举
            dfs(Vol+i*i*j,sum+i*2*j,now-1,i-1,j-1);//emmmm
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
        r[i]=i,h[i]=i;
    for(int i=1;i<=m;i++)
        S[i]=S[i-1]+r[i]*2*h[i];
    for(int i=1;i<=m;i++)
        V[i]=V[i-1]+r[i]*r[i]*h[i];
    dfs(0,0,m,28,28);
    if(ans==0x7fffffff) ans=0;
    printf("%d",ans);
}
原文地址:https://www.cnblogs.com/Lance1ot/p/9782195.html