洛谷P1731 [NOI1999]生日蛋糕

题目大意

    制作体积为Nπ的M层蛋糕,要求从上到下半径递减,高递减。输出使表面积Sπ最小的S。(N<=20000)(M<=15)。

思路:

   搜索,以下是几个剪枝:

  • 以后按最小搭建,余下的也体积不够,舍去。
  • 以后按最大搭建,余下的体积还有多余,舍去。
  • 以后表面积的最小值加上也比当前最优解大,舍去。
  • 半径的枚举顺序非常关键,要从大到小。因为半径对体积影响大,当半径较大时,高可以少枚举一点,更新mins也更早(如果rh都很小,会循环好几次知道r,h足够大才更新mins)。
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 
 6 using namespace std;
 7 
 8 int n,m,lifang[5000],s,mins,cnt[60],te;
 9 
10 void init()
11 {
12     lifang[1]=1;
13     for(int i=2;i<=m;i++)
14     {
15         lifang[i]=lifang[i-1]+i*i*i;
16     }
17     return ;
18 }
19 
20 void dfs(int ceng,int tiji,int rr,int hh)
21 {
22     if(ceng==m+1)
23     {
24         if(tiji==0)
25         {
26             mins=min(mins,s);
27         }
28         return ;
29     }
30     if(tiji-lifang[m-ceng+1]<0)return ;//以后按最小搭,余下的也体积不够。
31     if(ceng!=1)
32     {
33         long long tem=0;//以后按最大搭,余下的体积还有多余。
34         for(int i=1;i<=m-ceng+1;i++)
35         {
36             tem+=(rr-i)*(rr-i)*(hh-i);
37         }
38         if(tiji>tem)return ;
39     }
40     int t1,t2,t3;
41     t2=m-ceng+1;//最小值 
42     if(s+t2*(t2+1)*(2*t2+1)/3>=mins)return ;//以后表面积的最小值加上也比当前最优解大。
43     t1=sqrt((tiji-lifang[t2-1])/t2);//半径最大值。
44     t1=min(rr-1,t1); 
45     t3=(tiji-lifang[t2-1])/(t2*t2);//高最大值 
46     t3=min(hh-1,t3);
47     if(t2>t1)return ;
48     if(t2>t3)return ;
49     for(int r=t1;r>=t2;r--)//这个枚举顺序非常关键
50     {
51         for(int h=t2;h<=t3;h++)
52         {
53             s+=(h*r*2);
54             if(ceng==1)s+=r*r;
55             if((s>mins)||(tiji-r*r*h<lifang[t2-1]))//同第三个和第一个剪枝
56             {
57                 s-=(h*r*2);
58                 if(ceng==1)s-=r*r;
59                 break;
60             }
61             dfs(ceng+1,tiji-r*r*h,r,h);
62             s-=(h*r*2);
63             if(ceng==1)s-=r*r;
64         }
65     }
66     return ;
67 }
68 
69 int main()
70 {
71     scanf("%d%d",&n,&m);
72     mins=0x7fffffff;
73     init();
74     dfs(1,n,mins,mins);
75     if(mins==0x7fffffff)
76     {
77         printf("0\n");
78         return 0;
79     }
80     printf("%d\n",mins);
81     return 0;
82 }

 

posted @ 2018-11-15 23:32  liqgnonqfu  阅读(118)  评论(0编辑  收藏  举报