生日蛋糕
一道很經典也很基礎的搜尋題目。有題目的條件我們可以得到兩個方程:sum(rk*rk*hk) = n 和 s = sum(2*rk*hk)+r1*r1
首先考慮極端剪枝法。假設前i層體積為t,如果剩下的若干層,每層都去最小可能值,體積仍比n大,則剪去,如果剩下幾層都去最大值,體積仍比n小,也減去。如果當前的表面積比s大,則剪去。
然後考慮乙個隱藏的條件,我們可以由式子sum(rk * rk * hk) = n來考慮。假設前i層的體積為t * pi,表面積為w * pi ,那麼剩餘m-i層的體積滿足: n—t = sum(rk * rk *hk),其中i+1 <= k <= m ,而剩餘的表面積為:lefts = sum(2*rk * hk) i+1<=k<=m ,lefts = 2sum(rk*rk*hk/rk) >= 2*sum(rk*rk*hk/ri) = 2*(n-t)/ri= p ;如果p>= s-w
那麼lefts >= s-w ,於是我們在這裡也可以加以剪枝。只需要判斷一下即可。(參考了劉汝佳的演算法藝術與資訊學競賽)
#include #include #include #include using namespace std ;
int n ;
int m ;
int s ;
int nmin ;
//leftv 表示剩餘的體積 ,leftm剩餘的層數
//lastr上一層的半徑,lasth上一層的高度
void dfs(int leftv , int leftm , int lastr , int lasth)
//計算當前條件下最小的體積
int t ;
t = 0 ;
for(int i = leftm ; i > 0 ; i--)
//剩餘的最小體積仍大於剩下的體積
if(t > leftv)
return ;
//計算剩下的最大半徑
int maxr ;
int maxh ;
t -= leftm * leftm * leftm ;
maxr = (int)sqrt( 1.0 * (leftv - t)/leftm ) < lastr ? (int) sqrt(1.0 * (leftv - t)/leftm ) : lastr ;
for(int r = maxr ; r >= leftm ; r --)
if(maxv < leftv)
//如果是第一層,則加上上表面積
if(leftm == m)
if(nmin + 2 * r * h > s)
int v ;
v = leftv - r * r * h ;
//對應於第二種情況的剪枝
if(2 * v / r >= s - nmin - 2 * r * h)
continue ;
nmin += 2 * r * h ;
dfs(v , leftm - 1 , r - 1 , h - 1) ;
nmin -= 2 * r * h ;}}
}int main()
return 0 ;
}
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...
poj 1190 生日蛋糕
time limit 1000ms memory limit 10000k total submissions 17460 accepted 6221 7月17日是mr.w的生日,acm thu為此要製作乙個體積為n 的m層生日蛋糕,每層都是乙個圓柱體。設從下往上數第i 1 i m 層蛋糕是半徑為r...