生日蛋糕(dfs+剪枝)

生日蛋糕c++

 POJ - 1190 編程

題目:ide

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外,以上全部數據皆爲正整數) spa

Input.net

有兩行,第一行爲N(N <= 10000),表示待制做的蛋糕的體積爲Nπ;第二行爲M(M <= 20),表示蛋糕的層數爲M。code

Outputblog

僅一行,是一個正整數S(若無解則S = 0)。get

Sample Input數學

100it

2

Sample Output

68

Hint

圓柱公式 
體積V = πR 2
側面積A' = 2πRH 
底面積A = πR 2 

 

思路:

         很容易就能夠知道是按照層數進行dfs。當知足層數條件以及體積條件時,找到最小的答案就能夠輸出了。只是爲何想把這題目寫出來呢?由於這題目對時間的要求看似寬鬆,實則讓人想吐血。寫出來的dfs須要大量地剪枝,尤爲是hnust的oj上對剪枝的要求簡直是……太嚴格了。主要是須要剪枝的有三大類:

1)  n+minv[m-1]>N 當前已經計算出來的蛋糕的體積,加上剩下的層數中可能製造出的最少的蛋糕的體積的結果若是大於n,剪掉。

2)  sum+mins[m-1]>ans 當前已經計算出來的蛋糕的表面積,加上剩下層數中可能製造出的最少的蛋糕的表面積的結果若是大於以前計算出來的結果(ans)時,剪掉。

3)  sum+2*(N-n)/r>=ans 數學公式推導:n-sumv既所剩體積記做dv 還須要的表面積爲s

         s=2*ri*hi+2*r(i-1)*h(i-1)+... >=2*ri*hi*ri/r+2*r(i-1)*h(i-1)*r(i-1)/r+...

                             =2*dv/r(i從M-1取,r爲當前半徑 ri/r<1)

     因此獲得還須要的最小表面積s=2*(n-sum)/r,若是最小的s和已經搜索過的表面積sum依然比ans大 就不用繼續搜索了

若是仍是時間超限的話(例如hnust裏提供的數據)就須要第四次剪枝了。

4)當前計算出來的體積,加上可能的最大的蛋糕體積的結果小於n,剪掉。這個是參考了大佬的思路,就不貼出來了,都找獲得

 

AC代碼:

#include<bits/stdc++.h>

using namespace std; int h,r,N,M,mins[25],minv[25]; const int inf=1<<30; int ans=inf; int sum=0; void dfs(int r,int h,int n,int m,int sum) { if(m==0) { if(n==N&&sum<ans) { ans=sum;//cout<<r<<" "<<h<<endl;
 } return; } if(n+minv[m-1]>N||sum+mins[m-1]>ans||sum+2*(N-n)/r>=ans) return; for(int i=r-1; i>=m; i--) { int jl=i*i; if(m==M) sum=jl; int maxh=((N-n-minv[m-1])/(i*i)<h-1)? (N-n-minv[m-1])/(i*i):h-1; for(int j=maxh; j>=m; j--) { dfs(i,j,n+jl*j,m-1,sum+2*i*j); } } } int main() { minv[0]=0; mins[0]=0; for(int i=1; i<=20; i++) //從頂層向下計算出最小體積和表面積的可能值
 { //從頂層(即第一層)到第i層的最小體積minv[i]成立時第j層的半徑和高度都是j
        minv[i]=minv[i-1]+i*i*i; mins[i]=mins[i-1]+2*i*i; } while(scanf("%d %d",&N,&M)==2) { ans=inf; int rmax=(int)sqrt((double)N); //rmax初始半徑 底層半徑 最大值爲sqrt(n)
        int hmax=N;                    //hmax初始高度 高度最大爲 n
        dfs(rmax,hmax,0,M,0); if(ans==inf) cout<<0<<endl; else cout<<ans<<endl; } return 0; }
View Code
相關文章
相關標籤/搜索