现在的位置: 首页 > 综合 > 正文

POJ 1190 生日蛋糕 估计最小答案dfs剪枝

2018年04月25日 ⁄ 综合 ⁄ 共 940字 ⁄ 字号 评论关闭

题意:想做一个m层(每层是一个圆柱)总体积为n*pi的蛋糕抹奶油,想使得抹的奶油的面积/pi = s最小,问最小的s是多少。

题解:化简下得到sigma(ri * ri * hi)= n,s =sigma(2 * ri * hi) + h1 * h1,由于所有的数据都是不确定的没办法dp,只能暴搜了。
         很普通的一个剪枝是当前的值+未得到的最小值 >= ans直接跳出,开始从上到下dfs,但是一直TLE,然后看别人代码是从下向上dfs的,
         我想是因为大的放在下面的时候剩余需要填充的体积减少的很快,这样会减少dfs的深度。

Sure原创,转载请注明出处。

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <cmath>
#define MIN(a , b) ((a) < (b) ? (a) : (b))
using namespace std;
const int inf = 1 << 29;
int m,n,ans;

void dfs(int v,int c,int sr,int sh,int sum)
{
    if(c == m)
    {
        if(sum < ans)
        {
            ans = sum;
        }
        return;
    }
    if(sum + 2 * v / sr >= ans) return;   //估计剩下的最大的答案剪枝
    for(int i=sr;i>=m-c;i--)
    {
        int bj = v / (i * i) + 1;   //剩下部分的最大h
        if(sh < bj) bj = sh;
        if(i * i * bj * (m - c) < v) break;   //是否能构成v的体积
        if(c == 0) sum = i * i;
        for(int j=bj;j>=m-c;j--)
        {
            if(i * i * j + (i-1) * (i-1) * (j-1) * (m - c - 1) < v) break;    //是否能构成v的体积
            if(c < m-1 || i * i * j == v)
            {
                dfs(v - i * i * j , c+1 , i-1 , j-1 , sum + 2 * i * j);
            }
        }
    }
    return;
}

int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        ans = inf;
        int rmax = sqrt(1.0 * n / m) + 1;
        int hmax = n / m + 1;
        dfs(n,0,rmax,hmax,0);
        if(ans == inf) ans = 0;
        printf("%d\n",ans);
    }
    return 0;
}

抱歉!评论已关闭.