poj 1190 生日蛋糕

                                                                                                                   生日蛋糕
   
   

Description

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外,以上所有数据皆为正整数)

Input

有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。

Output

仅一行,是一个正整数S(若无解则S = 0)。

Sample Input

100
2

Sample Output

68

Hint

圆柱公式
体积V = πR 2H
侧面积A' = 2πRH

底面积A = πR2

解析:我们在计算过程中根本就没必要去带入π值,其次这个题的一大重点在于剪枝,我们可以得到三种剪枝方法,在代码中会解释

代码:    #include<stdio.h>  
    #define INF 10000000  
    #define min(a,b) (a<b?a:b)  
    int n,m,best,minv[22],mins[22];  
    void Init()  
    {  
         int i;  
         minv[0]=0;  
         mins[0]=0;  
         for(i=1;i<22;i++)//从顶层向下计算出最小体积和表面积的可能值  
         {  
            //从顶层(即第1层)到第i层的最小体积minv[i]成立时第j层的半径和高度都为i 
             minv[i]=minv[i-1]+i*i*i;  
             mins[i]=mins[i-1]+2*i*i;  
         }  
    }  
    //dep:搜索深度,从底层m层向上搜,r,h分别为该层的半径和高度  
    void DFS(int dep,int sumv,int sums,int r,int h)  
    {  
         int i,j,maxh;  
         if(dep==0)//搜索完成,则更新最小面积值  
         {  
             if(sumv==n&&sums<best)  //当涂的体积和要求体积相等时,比较当前涂过的面积和最优解
                best=sums;  
             return;  
         }  
         //剪枝如上面所述  
         if((sumv+minv[dep-1]>n//如果当前涂过的体积和我们在后面能够涂的最小体积之和都大于题目的要求体积,那么肯定不行)||(sums+mins[dep-1]>best//如果当前涂过的面积和我们在后面能够涂的最小面积之和都大于最优面积,那么肯定不行)||(2*(n-sumv)/r+sums>=best))  //我们涂过sums的面积,那么剩下的rest_s等于sum(2*Ri*Hi,一直到最后一层),肯定大于sum(2*Ri*Ri*Hi/r)(r为当前层的半径,由于我们是从下往上递推,那么Ri/r肯定小于1,因为从当前层往上推,半径在逐渐减小,因为sum(2*Ri*Ri*Hi)=2*(N-v)/r,sum(Ri*Ri*Hi)为后面几层的体积之和,并且2*(N-v)/r为剩下的几层的总侧面积)

             return;  
         //按递减顺序枚举dep层蛋糕半径的每一个可能值,这里第dep层的半径最小值为dep  
         for(i=r-1;i>=dep;i--)   
         {  
             if(dep==m)//底面积作为外表面积的初始值(总的上表面积,以后只需计算侧面积)  因为上层的底面积被它的下层所掩盖,我们加了之后,就不需要算它的顶部圆面积了,每次的dfs都会被计算在内了
                sums=i*i;  
             //最大高度,即dep层蛋糕高度的上限,(n-sumv-minv[dep-1])表示第dep层最大的体积  
             maxh=min((n-sumv-minv[dep-1])/(i*i),h-1);  
             for(j=maxh;j>=dep;j--)//同理,第dep层的最小高度值为dep  
                DFS(dep-1,sumv+j*i*i,sums+2*i*j,i,j);//递归搜索子状态  
         }  
    }  
      
    int main()  
    {  
        Init();  
        while(~scanf("%d%d",&n,&m))  
        {  
              best=INF;  
              DFS(m,0,0,n+1,n+1);  
              if(best==INF)  
                 best=0;  
              printf("%d\n",best);  
        }  
        return 0;  
    } 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值