poj1190 dfs剪枝

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 = πR2
侧面积A' = 2πRH 
底面积A = πR2 

Source

代码如下:

//

//  17day6_I.cpp

//  acm

//

//  Created by sakumi on 19/02/2017.

//  Copyright © 2017 sakumi. All rights reserved.

//

 

#include <cstdio>

#include <cmath>

#include <algorithm>

using namespace std;

int min_volume[21];

int min_area[21];

int r[21];

int h[21];

int ans,n,m;

const int INF=0x3f3f3f3f;

void dfs(int r_limit,int h_limit,int volume,int area,int layer)

{

    if(layer==0){

        if(volume!=n)return;

        ans=min(ans,area);

        return;

    }

    if(area>ans-min_area[layer])return;

    if(n-volume<min_volume[layer])return;

    if(ans-area<=2*(n-volume)/r_limit)return ;

    for(int i=r_limit;i>=layer;i--){

        if(layer==m){

            area=i*i;

        }

        int max_h=(n-min_volume[layer-1]-volume)/(i*i);

        for(int j=min(max_h,h_limit);j>=layer;j--){

            dfs(i-1,j-1,volume+i*i*j,area+2*i*j,layer-1);

        }

    }

}

int main()

{

    while(scanf("%d",&n)!=EOF){

        scanf("%d",&m);

        min_area[0]=min_volume[0]=0;

        for(int i=1;i<=20;i++){

            min_area[i]=min_area[i-1]+2*i*i;

            min_volume[i]=min_volume[i-1]+i*i*i;

        }

        ans=INF;

        dfs((int)sqrt(n),n,0,0,m);

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

    }

    return 0;

}

posted @ 2017-02-19 20:10  代码荒  阅读(272)  评论(0编辑  收藏  举报