生日蛋糕(DFS)
題意:
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?
思路:
由于深度一定(m),所以使用深度優先搜索,自上而下的設定蛋糕序號,最頂層的為第1層,……,最底層的蛋糕為第m層,很明顯滿足題目條件的前i層的(從頂層(也就是編號為1的層)開始計數)最小面積mins[i]和體積minv[i]是在該層的半徑以及高度都為i時取得,如果采用一般的神搜肯定會超時,所以這題還需要剪枝,剪枝條件有(從m層向上搜,假設前level層的體積為v,面積為s,當前所得的最小面積為best):?
1> 因為前level層的體積為v,如果剩下的幾層的體積都取最小可能值,總體積還是比n大,那么則說明前level層的方案不可行,所以可以剪枝(剪枝條件 為:v+minv[dep-1]>n)?
2> 因為前level層的面積為s,如果剩下的幾層的面積都取最小可能值,所得的面積和比已經得到的所求的最小面積best大,也可以進行剪枝(剪枝條件 為:s+mins[dep-1]>best)?
3> 因為前level層的體積為v,那么剩余的m-level層的體積滿足:n-v=(h[k](r[k]^2)+……+h[m](r[m]^2))(k=level+1,……,m)?
而剩余部分的表面積滿足:lefts=2*(r[k]h[k]+……+r[m]*h[m])>2(n-v)/r[level] (k=level+1,……,m)?
顯然有上述不等式lefts=best-s>2*(n-v)/r[level]。所以剪枝條件為:(2*(n-v)/r[level]+s>best)
#include<stdio.h> #include<math.h> #define cmp(a,b) (a<b?a:b) const int inf=0x7fffffff; int minv[21],mins[21]; int V,m; int ans; void dfs(int v,int s,int level,int r,int h)//level為搜索深度,從底層m層向上搜,r,h分別為該層的半徑和高度 {if(level==0){//搜索完成,則更新最小面積值if(v==V&&s<ans)ans=s;return;}if(v+minv[level-1]>V||s+mins[level-1]>ans||2*(V-v)/r+s>=ans)//剪枝1:return ;int i,j,h_now;for(i=r-1;i>=level;i--)//按遞減順序枚舉level層蛋糕半徑的每一個可能值,這里第level層的半徑最小值為level{if(level==m)//底面積作為外表面積的初始值(總的上表面積,以后只需計算側面積)s=i*i;h_now=cmp((V-v-minv[level-1])/(i*i),h-1); //最大高度,即level層蛋糕高度的上限,(n-v-minv[level-1])表示第level層最大的體積for(j=h_now;j>=level;j--)//同理,第level層的最小高度值為leveldfs(v+i*i*j,s+2*i*j,level-1,i,j);//遞歸搜索子狀態} } int main() {int i;minv[0]=0;mins[0]=0;for(i=1;i<=20;i++)//從頂層向下計算出最小體積和表面積的可能值{ //從頂層(即第一層)到第i層的最小體積minv[i]成立時第i層的半徑和高度都是iminv[i]=minv[i-1]+i*i*i;//不是每層的最最下體積,而是i~1層的最小體積。mins[i]=mins[i-1]+2*i*i;//同上}while(scanf("%d%d",&V,&m)==2){ans=inf;int r=sqrt(V/m)+1;//m層的最大半徑。int h=V/(m*m)+1;//m層的最大的高。dfs(0,0,m,r+1,h+1);if(ans==0x7fffffff)printf("0\n");elseprintf("%d\n",ans);}return 0; }
轉載于:https://www.cnblogs.com/pealicx/p/6115649.html
總結
- 上一篇: 20145106 《Java程序设计》第
- 下一篇: Python开发Day03