生日蛋糕——POJ1190——DFS+剪枝

本文介绍了一个使用深度优先搜索(DFS)算法解决特定生日蛋糕制作问题的案例。问题要求制作一个由多个圆柱体层组成的蛋糕,使得蛋糕外表面的总面积最小,同时满足给定的体积和层数条件。通过剪枝策略优化DFS算法,避免了超时问题,成功找到满足条件的最优解。
摘要由CSDN通过智能技术生成

DFS_生日蛋糕
添加链接描述
时间限制: 2 Sec 内存限制: 10 MB
提交: 516 解决: 102
题目描述
7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。
设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i < M时,要求Ri > Ri+1且Hi > Hi+1。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
令Q = Sπ
请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。
(除Q外,以上所有数据皆为正整数)

输入
有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。
输出
仅一行,是一个正整数S(若无解则S = 0)。
样例输入

100
2

样例输出

68
题意:蛋糕从下往上,每一层的半径和高都越来越小,且为整数。已知蛋糕的体积为Nπ,蛋糕的层数为M,输出S,使满足条件的蛋糕外表面(最下一层的下底面除外)的面积Q=Sπ最小。

解题思路:用DFS遍历每一层的蛋糕的高和半径,注意必须剪枝,否则会超时
斜体样式

AC代码:
#include <bits/stdc++.h>//万能头文件
using namespace std;
#define maxn 1000000007   
typedef long long ll;
int s,n,m,sum;
void DFS(int r,int h,int v,int s,int k)//参数分别代表半径,高,剩余体积,当前表面积,当前层数
{
    if(s+2*v/r>sum) return;  //剪枝:V=r1*r1*h1+r2*r2*h2+...     S=2*r1*h1+2*r2*h2+...
    if(k==m)             因为半径越来越小,所以2*v/r是剩余表面积的最小值,若s+2*v/r>当前最小表面积则不用继续递归
    {
        if(v==0) //层数和体积都满足条件则和最小表面积比较
        sum=min(sum,s);
        return; //不管体积满不满足,层数到了就不能继续递归
    }
    for(int R=r-1;R>=m-k;R--) //随着递归半径越来越小,且要保证最上面一层至少为1,从上往下半径越来越大,且
    {                           每一层半径都为整数,所以半径至少等于层数。(R>=m-k)
        int hk=min(h-1,v/(R*R));     //因为体积要减少R*R*H,所以H不
        for(int H=hk;H>=m-k;H--)     能超过v/(R*R),否则剩余体积为负
        {               
            int S;
            if(k==0)
                S=R*R+2*R*H;      //表面积要加上最下面的一个圆面
                else
                    S=s+2*R*H;
            DFS(R,H,v-R*R*H,S,k+1);
        }
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        sum=maxn; //最小表面积先赋初值
        DFS(sqrt(n)+1,n+1,n,0,0);  //因为v=r*r*h,所以半径最大为根号n,同理高最大为n,为避免出现不可知的错误,所以
        if(sum==maxn)                多加一个1....
            printf("0\n");          //一定要注意不要用cout<<,这题对时间要求很高,cout<<比较耗时,
        else                         因为这个找了一下午的BUG....
            printf("%d\n",sum);
    }
    return 0;
}
/**************************************************************
    Time:444 ms
    Memory:1740 kb
****************************************************************/

注:第一次发博客,还不太会,可能排版不好看…
而且还只是ACM入门小白,如果发现有问题请多多指教!( ̄▽ ̄)*

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Starry~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值