poj 1190 生日蛋糕(DFS+剪枝)

来源:互联网 发布:void在c语言中的意思 编辑:程序博客网 时间:2024/05/12 10:23
生日蛋糕
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 12965 Accepted: 4564

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

1002

Sample Output

68

Hint

圆柱公式 
体积V = πR2
侧面积A' = 2πRH 
底面积A = πR2 

Source

Noi 99


解题思路:蛋糕是从下往上逐渐减小的,表面积由各层蛋糕侧面积加顶面积,顶面积和为最底层蛋糕的顶面积,因此我们可以从最底层进行搜索。因为半径和高度都是整数,可以枚举,但直接搜必然超时,需要加上剪枝。

一共有两个剪枝:
1.
mind[i] 表示i层最小体积
mins[i] 表示i层最小侧面积 则
Si-1+2RiHi+mins[m-i] >= best
Di-1+Ri2Hi+mind[m-i] >= N
2.


当 s+2*剩余体积/Rk>=best时 可以剪枝


#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int N = 10000;const int M = 25;int n, m;int mincost;int mins[M], mind[M];void init(){    mins[0] = mind[0] = 0;    for(int i = 1; i < M; i++){        mins[i] = mins[i - 1] + 2 * i * i;        mind[i] = mind[i - 1] + i * i * i;    }}void dfs(int k, int r, int h, int s, int d){    if(k == m){        if(d == n && s < mincost) mincost = s;        return;    }    int ld = n - d;    for(int i = r - 1; i > m - k - 1; i--){        int maxh = h - 1;        maxh = min(maxh, (ld - mind[m - k - 1]) / (i * i));        for(int j = maxh; j > m - k - 1; j--){            int td = ld - i * i * j;            if(td < mind[m - k - 1]) continue;            int ts;            if(k == 0) ts = i * i + 2 * i * j;            else ts = s + 2 * i * j;            if(ts + mins[m - k - 1] >= mincost || (ts + 2 * td / i >= mincost)) continue;            dfs(k + 1, i, j, ts, d + i * i * j);        }    }}int main(){    init();    while(scanf("%d%d", &n, &m) != EOF){        mincost = 0x3fffffff;        dfs(0, N, N, 0, 0);        mincost == 0x3fffffff ? puts("0") : printf("%d\n", mincost);    }    return 0;}



0 0
原创粉丝点击