POJ 1190 生日蛋糕 DFS 優化剪枝

2021-06-22 00:40:41 字數 1907 閱讀 5434

poj 1190 生日蛋糕(dfs:優化剪枝)

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

hint

圓柱公式

體積v = πr2h

側面積a' = 2πrh

底面積a = πr2

分析:首先我們令最下面一層為第m層,然後最上面一層是第1層.那麼我們知道從下到上,每層的圓柱體半徑r和h都是整數且都遞減.

初始我們給出體積為v,層數為m,所以我們知道第m層的半徑r>=m且h>=m,所以我們可以通過第m層圓柱的體積r^2*h_max=vm

到這裡我們有了h和r的上界了.我們在求出sumv[i]表示從第一層到第i層的體積和最小值.以及sums[i]表示從第一層到第i層的側面積和最小值.

下面就是dfs了,我們令dfs(int floor,int prer,int preh,int leftv,ints)表示當前在第floor層,前一層floor+1時我們取了半徑為prer,高為preh.到了floor層我們還剩下leftv體積未分配,且我們已經產生了s的面積.

dfs的終態是:floor=0且leftv正好==0時,如果s的值< ans ,那麼我們就用s去更新ans.

當然dfs中還需要剪枝了.

第乙個剪枝是:

if((prer>1)&& 2 * vleft/(prer-1)+ s>=ans)

這句話的含義是如果剩下的體積只做成乙個圓柱體的話

,得到的側面積是最少的

,且如果這樣的話最後的總側面積還是大於

ans ,

那麼我們可以不用求下面的

dfs了

,無用功

.

第二個剪枝就是

:

if(vleft-sumv[floor]<0||s+sums[floor]>=ans)

剩餘的體積不足

,或者面積已經超了

.

ac**:

#include#includeusing namespace std;

int v,m;

int ans=65535;

int sumv[21],sums[21];

void dfs(int floor,int prer,int preh,int leftv,int s)

}int main()

int r_max=sqrt(1.0*v/m)+1;

int h_max=(1.0*v/(m*m))+1;

dfs(m,r_max,h_max,v,0);

if(ans==65535) ans=0;

printf("%d\n",ans);

}

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...

POJ 1190 生日蛋糕

time limit 1000ms memory limit 10000k total submissions 17060 accepted 6074 7月17日是mr.w的生日,acm thu為此要製作乙個體積為n 的m層生日蛋糕,每層都是乙個圓柱體。設從下往上數第i 1 i m 層蛋糕是半徑為r...