Poj 1190 生日蛋糕 回溯,減枝

2021-06-16 15:55:32 字數 1254 閱讀 4407

首先吐槽一下求面積和體積不用π。

其實不減枝的**還是很好寫的:

//m為蛋糕的層數

//v為當前已塗的體積

//s為當前已塗得到的s

//r和h為當前層的半徑和高

void dfs(int m,int v,int s,int r,int h)

//列舉可能的解

for(int i = r-1; i >= m; i--)

}}

然後就是減枝呢,四個減枝的條件:

先打表,算出每層蛋糕的最小體積和表面積(minv[i]和mins[i]),然後在來減枝

一、v+minv[m-1]  > v

v為已經塗的體積,那麼如果v加上下一層最小的體積比總體積v還大,這顯然是不可能的,減去

二、s+min[m-1] > ans

s為已經塗的面積,那麼s加上下一次最小的面積比當前求得的ans還大,顯然不需要dfs了,減去

三、2*(v-v)/r + s >= ans

已經塗了s,那麼還剩下rest_s = sum >= sum(2*ri*ri*hi/rk} = 2*(v-v)/r (設k為當前層的半徑)。如果rest_s加上s大於等於ans,那麼也不用在dfs了。

四、maxh = min((n-v-minv[m-1])/(i*i),h-1)

當列舉半徑為i時,當前最低的可能高為maxh = min((n-v-minv[m-1])/(i*i),h-1)。

下面是**:

#include#include#define maxn 22

#define inf 100000000

#define min(a,b) (a < b ? a : b)

int n;

int m;

int ans;

int minv[maxn],mins[maxn];

void init()

}//m為蛋糕的層數

//v為當前的體積

//s為當前得到的面積

//r和h為當前層的半徑和高

void dfs(int m,int v,int s,int r,int h)

if(s + mins[m-1] > ans || v + minv[m-1] > n || 2*(n-v)/r + s >= ans) return;

for(int i = r-1; i >= m; i--)

}}int main()

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