经典搜索题!!送给自己的生日礼物!!!
生日蛋糕
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 20000/10000K (Java/Other)
Total Submission(s) : 7 Accepted Submission(s) : 2
Problem 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外,以上所有数据皆为正整数)
设从下往上数第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
1002
Sample Output
68
Source
PKU
AC代码:
1 //Source Code 2 3 //Problem: 1190 User: CKboss 4 //Memory: 720K Time: 16MS 5 //Language: G++ Result: Accepted 6 //Source Code 7 8 9 #include <iostream> 10 #include <cmath> 11 12 #define INF 0xffff3f 13 14 using namespace std; 15 16 int n,m; 17 18 int mind[22]; 19 int mins[22]; 20 double best=INF; 21 22 void dfs(int k,int r,int h,int S,int D) 23 { 24 int i,j,ld; 25 if(k==m) 26 { 27 if(D==n&&S<best) best=S;//不断替换最小值 28 29 return ; 30 } 31 32 ld=n-D;//包括第K层到顶的体积 33 for(i=r-1;i>m-k-1;i--)//枚举可能的半径,(比下面的大,比上面的小) 34 { 35 int maxh,ts=0,td; 36 maxh=(ld-mind[m-k-1])/(i*i)+2;//判断最大高度 37 if(maxh>h-1) maxh=h-1; 38 for(j=maxh;j>m-k-1;j--) 39 { 40 41 td=ld-i*i*j; 42 if(td<mind[m-k-1]) continue;//1号剪枝 43 44 if(k==0) 45 ts=i*i+2*i*j; 46 else 47 ts=S+2*i*j; 48 49 if(ts+mins[m-k-1]>=best||ts+2*td/i>=best) continue;//2号,3号剪枝(3号比较厉害) 50 51 dfs(k+1,i,j,ts,D+i*i*j); 52 } 53 } 54 return ; 55 } 56 57 58 int main() 59 { 60 cin>>n>>m; 61 62 mind[0]=mins[0]=0; 63 for(int i=1;i<=21;i++) 64 { 65 mind[i]=mind[i-1]+i*i*i;//从顶到 i 的累计最小体积 66 mins[i]=mins[i-1]+2*i*i;//从顶到 i 的累计最小侧面积 67 } 68 69 dfs(0,sqrt(n)+1,n+1,0,0);//分别以半径为1,或高为1算最大的可能取值 70 71 if(best!=INF) 72 cout<<best<<endl; 73 else 74 cout<<0<<endl; 75 76 77 return 0; 78 }