洛谷 1731 生日蛋糕 dfs+剪枝

题目:

https://www.luogu.org/problem/show?pid=1731

加了四个剪枝;

明确枚举的对象——每层的高度和半径;
∑表面积=∑圆柱侧面积+最大的底面积;(画图);

总结:
注意细节;

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;

int V,n,ans=1<<23;
int minV[1001],minA[1001];

int calc(int tot,int r,int h)
{//每一层都为最大体积的情况,
    int v=0;
    for(int i=0;i<tot;i++)//h,r每次只减1;
        v+=(r-i)*(r-i)*(h-i);
    return v;
}


void dfs(int v,int tot,int r,int h,int s)
{
    if(tot==0)
    {
        if(v) return;
        ans=min(s,ans);
        return;
    }
    if(v<=0) return;
    if(s+minA[tot]>=ans) return;//前面的面积+当前最小面积>答案
    if(minV[tot]>v) return;//剩余体积<当前最小体积都无法更新;
    if(calc(tot,r,h)<v) return;//剩余层数"用最大的体积"仍小于剩余体积
    if(r<tot || h<tot) return;//r,h至少等于层数;


    for(int i=r;i>=tot;i--)//半径;
    {
        if(tot==n) s=i*i;
        for(int j=h;j>=tot;j--)//高度;
            dfs(v-i*i*j,tot-1,i-1,j-1,s+2*i*j);
    }
    return;
}


void solve()
{
    scanf("%d%d",&V,&n);
    for(int i=1;i<=n;i++)//预处理每层最小体积与面积.方便剪枝;
        minV[i]=minV[i-1]+i*i*i,minA[i]=minA[i-1]+2*i*i;
    if(minV[n]>V) {cout<<0<<endl;return;}
//  cout<<minV[n]<<endl;

    int maxH=(V-minV[n-1])/(n*n)+1;//V-minV[n-1]为最大体积,n为最小半径;
    int maxR=sqrt((double)(V-minV[n-1])/n)+1;//同理;

    dfs(V,n,maxR,maxH,0);
    if(ans== 1<<23 ) cout<<"0";

    else cout<<ans;
}

int main()
{
    solve();
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值