题目背景
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<=20000),表示待制作的蛋糕的体积为Nπ;第二行为M(M<=15),表示蛋糕的层数为M。
输出格式:仅一行,是一个正整数S(若无解则S=0)。
输入输出样例
题解
可以说是童年阴影了。
众所周知的一道爆搜题,考点大概是剪枝?
1 /* 2 qwerta 3 P1731 [NOI1999]生日蛋糕 4 Accepted 5 100 6 代码 C++,1.45KB 7 提交时间 2018-10-10 11:55:48 8 耗时/内存 9 760ms, 1256KB 10 */ 11 #include<iostream> 12 #include<cstdio> 13 #include<cmath> 14 using namespace std; 15 #define R register 16 int n,m; 17 long long q=999999999999999; 18 int f[16][103][10003]; 19 int fx[21][2]; 20 void search(int d,int rbef,int hbef,int vres,int sbef)//d:深度 rbef:上一层半径 hbef:上一层高度 vres:还剩的体积 sbef:已经用了多少面积 21 { 22 if(d==m+1) 23 { 24 if(vres==0) 25 q=min(q,(long long)sbef);//搜到了就更新 26 return; 27 } 28 if(vres<=0)return;//没体积了,剪掉 29 if(sbef>q)return;//面积大了,剪掉 30 if(rbef<=(m-d+1))return;//半径小了不够搭这么多层,剪掉 31 if(hbef<=(m-d+1))return;//高度矮了不够搭这么多层,剪掉 32 if(2*vres/rbef+sbef>q)return;//划重点!如果当前体积的最小面积还大了,剪掉 33 // 34 if(fx[d][0])//记忆化 fx[d][0]记录还剩d层时至少要的体积,fx[d][1]为面积 35 { 36 if(fx[d][0]>vres)return;//剩体积的不够用,剪掉 37 if(fx[d][1]+sbef>q)return;//最小的法子涂也面积大了,剪掉 38 } 39 else 40 { 41 int v=0,s=0; 42 for(R int i=d;i<=m;++i)//for一遍 43 { 44 int r=(m+1-i); 45 int h=(m+1-i); 46 v+=r*r*h,s+=2*r*h; 47 } 48 fx[d][0]=v; 49 fx[d][1]=s; 50 if(v>vres)return; 51 if(s+sbef>q)return; 52 } 53 // 54 if(f[d][rbef][hbef])//记录在d,rbef,hbef的情况下的最大体积 55 { 56 if(f[d][rbef][hbef]<vres)return;//往大了搭还小了,剪掉 57 } 58 else 59 { 60 int v=0; 61 for(R int i=d;i<=m;++i) 62 { 63 int r=(rbef-(i-(d-1))); 64 int h=(hbef-(i-(d-1))); 65 v+=r*r*h; 66 } 67 f[d][rbef][hbef]=v; 68 if(v<vres)return; 69 } 70 //剪爽了,开始搜 71 for(R int r=1;r<rbef;++r) 72 for(R int h=1;h<hbef;++h) 73 { 74 int s=0; 75 if(d==1)s=r*r; 76 search(d+1,r,h,vres-r*r*h,sbef+s+2*r*h); 77 } 78 return; 79 } 80 int main() 81 { 82 //freopen("a.in","r",stdin); 83 scanf("%d%d",&n,&m); 84 search(1,101,10001,n,0); 85 cout<<q; 86 return 0; 87 }