題解
也就是說第m層蛋糕的半徑最小為m,高最小也是m (此時第一層蛋糕半徑和高都是1保證第m層最小)
1.for(int i=m;i*i*m<=n;i++)//i表示的是半徑的範圍
2.for(int j=m;i*i*j<=n;j++)
//j表示的是高的範圍
3.if(i*i+2*i*j
//這一步表示的是只有我們在列舉到這個表面積小於我們之前記錄過的才可以繼續(最優化剪枝)
4.dfs(1,i*i*j,i*i+2*i*j,i,j)
//進入遞迴函式
/*1.從前1層開始
2.體積為i*i*j
3.表面積為2*i*j
4.i表示半徑
5.j表示高
*/
minn 表示到目前為止的最小表面積通過剪枝,不斷向下繼續搜一層解釋一下 dfs
void dfs(int d,int v,int s,int r,int
h)//
列舉了d層,前d層體積為v,表面積為s,第d層半徑為r,高為h
剪枝:
(1)如果 (d==m) 說明已經列舉夠層數了,如果 (v==n) ,記錄下此時表面積,就是答案
(2)如果 v加上剩下m-d層蛋糕體積的最大值還不能到達 n 的話,捨去
由於題目要求蛋糕半徑和高均是遞減的
所以剩下蛋糕層數的半徑最大為 r-1 ,高最大為 h-1 ,還剩 m-d 層
(3)如果 v加上剩下m-d層蛋糕體積的最小值還超過 n 的話,捨去
由於題目要求蛋糕半徑和高均是遞減的
所以剩下蛋糕層數的半徑最小為
1 ,高最小為 1 ,還剩 m-d 層
最小的話,最上面一層半徑,高一定為1 (4
)最優化剪枝
前d層蛋糕的體積 v=r[1]*r[1]*h[1]+...+r[d]*r[d]*h[d] < r*r[1]*h[1]+...+r*r[d]*h[d]
(這裡r是最底層蛋糕半徑)
顯然n-v< r*r[1]*h[1]+...+r*r[d]*h[d]
兩邊同時/r *2
那麼左邊
2*(n-v)/r
右邊就是
2*r[1]*h[1]+...+2*r[d]*h[d] ,也就是之前記錄的前d層表面積 minn
也就是要保證 s+2*(n-v)/r
**
#include#include感謝這個神仙#include
#include
#include
#include
#include
#include
using
namespace
std;
int n,m,minn=2e9+1
;void dfs(int d,int v,int s,int r,inth)
if(v+(r-1)*(r-1)*(h-1)*(m-d)return
;
if(v+m-d>n) return
;
if(2*(n-v)/r+s>=minn) return
;
for(int i=r-1;i>=m-d;i--)
for(int j=h-1;j>=m-d;j--)
if((v+i*i*j<=n)&&(s+2*i*j
dfs(d+1,v+i*i*j,s+2*i*j,i,j);
}int
main()
1710 生日蛋糕
1710 生日蛋糕1999年noi全國競賽 時間限制 2 s 空間限制 128000 kb 7月17日是mr.w的生日,acm thu為此要製作乙個體積為n 的m層生日蛋糕,每層都是乙個圓柱體。設從下往上數第i 1 i m 層蛋糕是半徑為ri,高度為hi的圓柱。當iri 1且hi hi 1。由於要在...
POJ 1190 生日蛋糕
生日蛋糕 一道很經典也很基礎的搜尋題目。有題目的條件我們可以得到兩個方程 sum rk rk hk n 和 s sum 2 rk hk r1 r1 首先考慮極端剪枝法。假設前i層體積為t,如果剩下的若干層,每層都去最小可能值,體積仍比n大,則剪去,如果剩下幾層都去最大值,體積仍比n小,也減去。如果當...
POJ 1190 生日蛋糕
呵呵,這道題弄死我。我覺得吧,凡事不能急於求成,比如這道經典的剪枝 搜尋,我就先查的題解,看了各種剪枝方法躊躇滿志,結果花了兩個小時寫的剪枝把自己都搞暈了。應該先有正確的搜尋方法再談剪枝不是嗎,所以我決定先用樸素的搜尋做一下 include includeint n,m int temp s 999...