1. 程式人生 > >POJ 1190 生日蛋糕

POJ 1190 生日蛋糕

POJ 1190 生日蛋糕 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 23271 Accepted: 8320 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 Hint

圓柱公式 體積V = πR2H 側面積A’ = 2πRH 底面積A = πR2

重刷POJ的第一題,經典搜尋之——生日蛋糕。 題意:求製作一個m層,體積為v的蛋糕需要奶油的最小表面積,限制條件為:下面一層的半徑以及高度至少要比上一層的大1. 題解:用**dfs(int r 當前的半徑,int h當前的高度,int q當前的表面積,int deep當前的層數,int v當前的體積)**維護 值得深思的是,用dfs搜尋必須要有一個極限,那麼r的極限是什麼?h的極限是什麼? 我們不妨假設整個蛋糕只有一個圓柱,因為體積最大為10000,所以如果其高度為1,那麼r最大為100;如果其半徑為1,那麼高度最大為10000; 那麼就可以有如下的程式碼:

	dfs(100,10000,0,m,0);

int dfs(int r,int h,int q,int deep,int v)
{
    if(deep<0) return 0;
    if(deep==0&&v==n){//當滿足條件時,更新最優解。
        if(q+pre_r*pre_r<ans) ans=q+pre_r*pre_r;
        return 0;
    }

/*
從最下層往上列舉。
*/
    for(int i=r-1;i>=deep;i--)
    {
        if(deep==m) pre_r=i;
        for(int j=h-1;j>=deep;j--)
        {
            dfs(i,j,q+2*i*j,deep-1,v+i*i*j);
        }
    }
}

這樣還不行,我們還需要考慮剪枝

  1. 從下往上列舉;
  2. 當deep<0時return;
  3. 當 當前體積大於n,return;
  4. 當 當前表面積大於ans;return;
  5. 當 就算剩下的層數取最大體積仍不足以使體積≥v;return

以下為程式碼:

#include <iostream>

using namespace std;
int n,m;
int ans=0x7fffffff;
int pre_r;//最下面一層的半徑
int dfs(int r,int h,int q,int deep,int v)
{
    if(q+pre_r*pre_r>ans||v>n||deep<0) return 0;//剪枝2、3、4
    if(deep==0&&v==n){
        if(q+pre_r*pre_r<ans) ans=q+pre_r*pre_r;
        return 0;
    }


    for(int i=r-1;i>=deep;i--)//剪枝1
    {
        if(deep==m) pre_r=i;
        for(int j=h-1;j>=deep;j--)
        {
        //****************************//**剪枝5**
            int sum=0;
            for(int k=0;k<=deep-1;k++)
                sum+=(i-k)*(i-k)*(j-k);
            if(sum+v<n)continue;
         //********************************
            dfs(i,j,q+2*i*j,deep-1,v+i*i*j);
        }
    }
}


int main()
{
    cin>>n>>m;
    dfs(100,10000,0,m,0);
    if(ans==0x7fffffff) ans=0;
    cout<<ans<<endl;
}